Initial commit

This commit is contained in:
2025-08-20 19:02:58 +08:00
commit f6b2677c0f
8577 changed files with 1307117 additions and 0 deletions

2
lib/asyncmsg/Makefile Normal file
View File

@@ -0,0 +1,2 @@
LIST=CPU
include recurse.mk

View File

@@ -0,0 +1,107 @@
/*
* $QNXLicenseC:
* Copyright 2007, QNX Software Systems. All Rights Reserved.
*
* You must obtain a written license from and pay applicable license fees to QNX
* Software Systems before you may reproduce, modify or distribute this software,
* or any work that includes all or part of this software. Free development
* licenses are available for evaluation and non-commercial purposes. For more
* information visit http://licensing.qnx.com or email licensing@qnx.com.
*
* This file may contain contributions from others. Please review this entire
* file for other proprietary rights or license notices, as well as the QNX
* Development Suite License Guide at http://licensing.qnx.com/license-guide/
* for other information.
* $
*/
#include <errno.h>
#include <pthread.h>
#include <stdlib.h>
#include "asyncmsg_priv.h"
#define _ASYNCMSG_HANDLE_LIST_GROW 4
struct _asyncmsg_handle_list {
pthread_rwlock_t rwlock;
void **array;
int array_total;
};
static struct _asyncmsg_handle_list _channel_list = {
PTHREAD_RWLOCK_INITIALIZER, 0, 0
};
static struct _asyncmsg_handle_list _fd_list = {
PTHREAD_RWLOCK_INITIALIZER, 0, 0
};
static struct _asyncmsg_handle_list _connect_list = {
PTHREAD_RWLOCK_INITIALIZER, 0, 0
};
void * _asyncmsg_handle(int id, int cmd, void *handle)
{
struct _asyncmsg_handle_list *list;
if (cmd & _ASYNCMSG_HANDLE_CHANNEL) {
cmd &= ~_ASYNCMSG_HANDLE_CHANNEL;
list = &_channel_list;
} else if (id & _NTO_SIDE_CHANNEL) {
list = &_connect_list;
id &= ~_NTO_SIDE_CHANNEL;
} else {
list = &_fd_list;
}
if (cmd == _ASYNCMSG_HANDLE_ADD) {
if ((errno = pthread_rwlock_wrlock(&list->rwlock)) != EOK) {
return NULL;
}
if (list->array_total <= id) {
void **new_array;
size_t new_size;
int extra;
if ((extra = id - list->array_total + 1) < _ASYNCMSG_HANDLE_LIST_GROW)
extra = _ASYNCMSG_HANDLE_LIST_GROW;
new_size = (list->array_total + extra) * sizeof(void *);
if ((new_array = realloc(list->array, new_size)) == NULL) {
pthread_rwlock_unlock(&list->rwlock);
return NULL;
}
memset(&new_array[list->array_total], 0, extra * sizeof(void *));
list->array = new_array;
list->array_total += extra;
}
list->array[id] = handle;
pthread_rwlock_unlock(&list->rwlock);
return handle;
}
if (id >= list->array_total) {
errno = ESRCH;
return NULL;
}
if ((errno = pthread_rwlock_rdlock(&list->rwlock)) != EOK) {
return NULL;
}
handle = list->array[id];
if (cmd & _ASYNCMSG_HANDLE_DELETE) {
list->array[id] = NULL;
}
pthread_rwlock_unlock(&list->rwlock);
if (!handle)
errno = ESRCH;
return handle;
}
__SRCVERSION("_asyncmsg_handle.c $Rev: 157149 $");

View File

@@ -0,0 +1,8 @@
LIST=VARIANT
ifndef QRECURSE
QRECURSE=recurse.mk
ifdef QCONFIG
QRDIR=$(dir $(QCONFIG))
endif
endif
include $(QRDIR)$(QRECURSE)

View File

@@ -0,0 +1 @@
include ../../common.mk

View File

@@ -0,0 +1 @@
include ../../common.mk

View File

@@ -0,0 +1 @@
include ../../common.mk

View File

@@ -0,0 +1 @@
include ../../common.mk

View File

@@ -0,0 +1,69 @@
/*
* $QNXLicenseC:
* Copyright 2007, QNX Software Systems. All Rights Reserved.
*
* You must obtain a written license from and pay applicable license fees to QNX
* Software Systems before you may reproduce, modify or distribute this software,
* or any work that includes all or part of this software. Free development
* licenses are available for evaluation and non-commercial purposes. For more
* information visit http://licensing.qnx.com or email licensing@qnx.com.
*
* This file may contain contributions from others. Please review this entire
* file for other proprietary rights or license notices, as well as the QNX
* Development Suite License Guide at http://licensing.qnx.com/license-guide/
* for other information.
* $
*/
#include <errno.h>
#include <stdlib.h>
#include "asyncmsg_priv.h"
/* This is painful. We have to prepare receive buf, and associate
* it with the chid, so we will know where to receive
*/
int asyncmsg_channel_create(unsigned flags, mode_t mode, size_t buffer_size, unsigned max_num_buffer, const struct sigevent *ev, int (*recvbuf_callback)(size_t bufsize, unsigned num_bufs, void*bufs[], int flags))
{
struct _asyncmsg_channel_context *acc;
int chid;
if ((acc = (struct _asyncmsg_channel_context *)malloc(sizeof(*acc))) == NULL) {
return -1;
}
memset(acc, 0, sizeof(*acc));
if ((errno = pthread_mutex_init(&acc->mutex, 0)) != EOK) {
free(acc);
return -1;
}
acc->recvbuf_cb = recvbuf_callback;
acc->max_num_buffer = max_num_buffer;
acc->buffer_size = buffer_size;
if ((acc->iovs = malloc(sizeof(iov_t) * max_num_buffer)) == NULL) {
free(acc);
return -1;
}
if ((chid = ChannelCreateExt(flags | _NTO_CHF_ASYNC, mode, buffer_size, max_num_buffer, ev, NULL)) == -1) {
pthread_mutex_destroy(&acc->mutex);
free(acc->iovs);
free(acc);
return -1;
}
if (_asyncmsg_handle(chid, _ASYNCMSG_HANDLE_ADD | _ASYNCMSG_HANDLE_CHANNEL, acc) == NULL) {
asyncmsg_channel_destroy(chid);
free(acc->iovs);
free(acc);
return -1;
}
return chid;
}
__SRCVERSION("asyncmsg_channel_create.c $Rev: 153052 $");

View File

@@ -0,0 +1,75 @@
/*
* $QNXLicenseC:
* Copyright 2007, QNX Software Systems. All Rights Reserved.
*
* You must obtain a written license from and pay applicable license fees to QNX
* Software Systems before you may reproduce, modify or distribute this software,
* or any work that includes all or part of this software. Free development
* licenses are available for evaluation and non-commercial purposes. For more
* information visit http://licensing.qnx.com or email licensing@qnx.com.
*
* This file may contain contributions from others. Please review this entire
* file for other proprietary rights or license notices, as well as the QNX
* Development Suite License Guide at http://licensing.qnx.com/license-guide/
* for other information.
* $
*/
#include <stdlib.h>
#include "asyncmsg_priv.h"
int asyncmsg_channel_destroy(int chid)
{
struct _asyncmsg_channel_context *acc;
if (ChannelDestroy(chid) == -1) {
return -1;
}
if ((acc = _asyncmsg_handle(chid, _ASYNCMSG_HANDLE_DELETE | _ASYNCMSG_HANDLE_CHANNEL, 0)) == NULL)
{
return -1;
}
/* how do we destroy mutex safely ? */
pthread_mutex_destroy(&acc->mutex);
if (acc->free) {
if (!acc->recvbuf_cb) {
struct _asyncmsg_get_header *ahp;
while (ahp = acc->free) {
acc->free = ahp->next;
asyncmsg_free(ahp);
}
} else {
int i, n;
void **buffs, *single_buf;
if ((buffs = alloca(acc->num_free * sizeof(void *))) == NULL) {
buffs = &single_buf;
n = 1;
} else {
n = acc->num_free;
}
do {
for (i = 0; i < n; i++) {
buffs[i] = acc->free;
acc->free = acc->free->next;
}
acc->recvbuf_cb(acc->buffer_size + sizeof(iov_t) + sizeof(struct _asyncmsg_get_header),
n, buffs, ASYNCMSG_RECVBUF_FREE);
acc->num_free -= n;
} while (acc->num_free);
}
}
free(acc->iovs);
free(acc);
return 0;
}
__SRCVERSION("asyncmsg_channel_destroy.c $Rev: 153052 $");

View File

@@ -0,0 +1,181 @@
/*
* $QNXLicenseC:
* Copyright 2007, QNX Software Systems. All Rights Reserved.
*
* You must obtain a written license from and pay applicable license fees to QNX
* Software Systems before you may reproduce, modify or distribute this software,
* or any work that includes all or part of this software. Free development
* licenses are available for evaluation and non-commercial purposes. For more
* information visit http://licensing.qnx.com or email licensing@qnx.com.
*
* This file may contain contributions from others. Please review this entire
* file for other proprietary rights or license notices, as well as the QNX
* Development Suite License Guide at http://licensing.qnx.com/license-guide/
* for other information.
* $
*/
#include <errno.h>
#include <pthread.h>
#include <stdlib.h>
#include <sys/mman.h>
#include "asyncmsg_priv.h"
static struct sigevent *_async_ev;
static pthread_t _async_ev_tid;
static void * _async_event_thread(void *arg)
{
int chid = (int)arg, coid;
struct _pulse pulse;
struct _asyncmsg_connect_context *acc;
struct _asyncmsg_connection_descriptor *acd;
for (;;) {
if (MsgReceivePulse(chid, &pulse, sizeof(pulse), NULL) == -1)
return NULL;
coid = pulse.value.sival_int;
if ((acc = _asyncmsg_handle(coid, _ASYNCMSG_HANDLE_LOOKUP, 0)) == NULL)
continue;
acd = &acc->acd;
_mutex_lock(&acd->mu);
if (pulse.code == 'T') {
/* triger timer expired */
if (acc->acd.num_curmsg) {
MsgSendAsync(coid);
}
acc->flags |= _ASYNCMSG_CONNECT_TIMEROFF;
_mutex_unlock(&acd->mu);
continue;
}
if (pulse.code == 'P')
{
/* collect some done message from "free" ptr */
struct _asyncmsg_put_header *aph;
while (acd->sendq_free != acd->sendq_head) {
aph = &acd->sendq[acd->sendq_free];
if (aph->cb) {
aph->cb(aph->err, aph->iov, aph->handle);
} else if (acd->attr.call_back) {
acd->attr.call_back(aph->err, aph->iov, aph->handle);
}
if (++acd->sendq_free >= acd->sendq_size)
acd->sendq_free = 0;
}
/* Sigh! have to use broadcast cause the condvar both
* use for queue full, and asyncmsg_flush()
*/
pthread_cond_broadcast(&acd->block_con);
_mutex_unlock(&acd->mu);
}
}
}
int asyncmsg_connect_attach(uint32_t nd, pid_t pid, int chid, unsigned index, unsigned flags, const struct _asyncmsg_connection_attr *attr)
{
struct _asyncmsg_connect_context *acc;
struct _asyncmsg_connection_descriptor *acd;
int id, size;
static pthread_mutex_t _async_init_mutex = PTHREAD_MUTEX_INITIALIZER;
_mutex_lock(&_async_init_mutex);
if (!_async_ev) {
int chid;
if ((_async_ev = malloc(sizeof(*_async_ev))) == NULL) {
_mutex_unlock(&_async_init_mutex);
return -1;
}
if ((chid = ChannelCreate(0)) == -1)
{
free(_async_ev);
_async_ev = NULL;
_mutex_unlock(&_async_init_mutex);
return -1;
}
if ((_async_ev->sigev_coid = ConnectAttach(0, 0, chid, _NTO_SIDE_CHANNEL, 0)) == -1)
{
ChannelDestroy(chid);
free(_async_ev);
_async_ev = NULL;
_mutex_unlock(&_async_init_mutex);
return -1;
}
_async_ev->sigev_notify = SIGEV_PULSE;
_async_ev->sigev_priority = SIGEV_PULSE_PRIO_INHERIT;
if ((errno = pthread_create(&_async_ev_tid, NULL, _async_event_thread, (void *)chid)) != EOK)
{
ConnectDetach(_async_ev->sigev_coid);
ChannelDestroy(chid);
free(_async_ev);
_async_ev = NULL;
_mutex_unlock(&_async_init_mutex);
return -1;
}
}
_mutex_unlock(&_async_init_mutex);
size = sizeof(*acc) + sizeof(struct _asyncmsg_put_header) * attr->max_num_buffer;
acc = mmap(0, size, PROT_READ|PROT_WRITE, MAP_PRIVATE | MAP_ANON | MAP_PHYS, NOFD, 0);
if (acc == (struct _asyncmsg_connect_context *)MAP_FAILED) {
return -1;
}
memset(acc, 0, sizeof(*acc));
acd = &acc->acd;
flags |= _NTO_COF_NOSHARE;
acd->attr = *attr;
acd->flags = flags;
acd->sendq_size = attr->max_num_buffer;
acd->sendq = (struct _asyncmsg_put_header *)((char *)acc + sizeof(*acc));
if ((id = ConnectAttachExt(nd, pid, chid, index, flags, acd)) == -1) {
return -1;
}
acd->sendq_head = acd->sendq_tail = acd->sendq_free = 0;
acd->ev = *_async_ev;
acd->ev.sigev_value.sival_int = id;
acd->ev.sigev_code = 'T';
if ((acd->ttimer = TimerCreate(CLOCK_REALTIME, &acd->ev)) == (timer_t)-1) {
asyncmsg_connect_detach(id);
return -1;
}
acc->flags = _ASYNCMSG_CONNECT_TIMEROFF;
acd->ev.sigev_code = 'P';
if ((errno = pthread_mutex_init(&acd->mu, 0)) != EOK)
{
asyncmsg_connect_detach(id);
return -1;
}
if ((errno = pthread_cond_init(&acd->block_con, 0)) != EOK)
{
asyncmsg_connect_detach(id);
return -1;
}
if (_asyncmsg_handle(id, _ASYNCMSG_HANDLE_ADD, acc) == NULL) {
asyncmsg_connect_detach(id);
return -1;
}
return id;
}
__SRCVERSION("asyncmsg_connect_attach.c $Rev: 153052 $");

View File

@@ -0,0 +1,48 @@
/*
* $QNXLicenseC:
* Copyright 2007, QNX Software Systems. All Rights Reserved.
*
* You must obtain a written license from and pay applicable license fees to QNX
* Software Systems before you may reproduce, modify or distribute this software,
* or any work that includes all or part of this software. Free development
* licenses are available for evaluation and non-commercial purposes. For more
* information visit http://licensing.qnx.com or email licensing@qnx.com.
*
* This file may contain contributions from others. Please review this entire
* file for other proprietary rights or license notices, as well as the QNX
* Development Suite License Guide at http://licensing.qnx.com/license-guide/
* for other information.
* $
*/
#include "asyncmsg_priv.h"
int asyncmsg_connect_attr(int coid, struct _asyncmsg_connection_attr *old_attr, const struct _asyncmsg_connection_attr *new_attr)
{
struct _asyncmsg_connect_context *acc;
struct _asyncmsg_connection_descriptor *acd;
if ((acc = _asyncmsg_handle(coid, _ASYNCMSG_HANDLE_LOOKUP, 0)) == NULL)
return -1;
acd = &acc->acd;
_mutex_lock(&acd->mu);
if (old_attr) {
*old_attr = acd->attr;
}
if (new_attr) {
acd->attr = *new_attr;
/* I can't change max_buffer_size/buff_size, these
* will causing acd->start changed, which means, the
* memory kernel is referencing will gone :-(
*/
}
_mutex_unlock(&acd->mu);
return 0;
}
__SRCVERSION("asyncmsg_connect_attr.c $Rev: 153052 $");

View File

@@ -0,0 +1,79 @@
/*
* $QNXLicenseC:
* Copyright 2007, QNX Software Systems. All Rights Reserved.
*
* You must obtain a written license from and pay applicable license fees to QNX
* Software Systems before you may reproduce, modify or distribute this software,
* or any work that includes all or part of this software. Free development
* licenses are available for evaluation and non-commercial purposes. For more
* information visit http://licensing.qnx.com or email licensing@qnx.com.
*
* This file may contain contributions from others. Please review this entire
* file for other proprietary rights or license notices, as well as the QNX
* Development Suite License Guide at http://licensing.qnx.com/license-guide/
* for other information.
* $
*/
#include <stdlib.h>
#include <errno.h>
#include <sys/mman.h>
#include "asyncmsg_priv.h"
int asyncmsg_connect_detach(int coid)
{
struct _asyncmsg_connect_context *acc;
struct _asyncmsg_connection_descriptor *acd;
struct _asyncmsg_put_header *aph;
if (ConnectDetach(coid) == -1)
return -1;
if ((acc = _asyncmsg_handle(coid, _ASYNCMSG_HANDLE_DELETE, 0)) == NULL)
return -1;
timer_delete(acc->acd.ttimer);
/* if there is still message in the queue, remove them. The q is like:
*
* (free slot we know) --- (kernel point here) --- (lib point here)
* free head tail
*
* free to head are already processed by kernel,
* head to tail are messages already aysncmsg_put() but not processed,
* tail to free are free slot for further asyncmsg_put().
*/
acd = &acc->acd;
_mutex_lock(&acd->mu);
while (acd->sendq_free != acd->sendq_tail) {
aph = &acd->sendq[acd->sendq_free];
/* cast to int to protect wrap over */
if ((int)(acd->sendq_free - acd->sendq_head) >= 0) {
aph->err = EBADF;
}
if (aph->cb) {
aph->cb(aph->err, aph->iov, aph->handle);
} else if (acd->attr.call_back) {
acd->attr.call_back(aph->err, aph->iov, aph->handle);
}
if (++acd->sendq_free >= acd->sendq_size)
acd->sendq_free = 0;
}
/* Sigh! have to use broadcast cause the condvar both
* use for queue full, and asyncmsg_flush()
*/
pthread_cond_broadcast(&acd->block_con);
_mutex_unlock(&acd->mu);
pthread_cond_destroy(&acc->acd.block_con);
pthread_mutex_destroy(&acc->acd.mu);
munmap(acc, sizeof(*acc));
return 0;
}
__SRCVERSION("asyncmsg_connect_detach.c $Rev: 153052 $");

View File

@@ -0,0 +1,46 @@
/*
* $QNXLicenseC:
* Copyright 2007, QNX Software Systems. All Rights Reserved.
*
* You must obtain a written license from and pay applicable license fees to QNX
* Software Systems before you may reproduce, modify or distribute this software,
* or any work that includes all or part of this software. Free development
* licenses are available for evaluation and non-commercial purposes. For more
* information visit http://licensing.qnx.com or email licensing@qnx.com.
*
* This file may contain contributions from others. Please review this entire
* file for other proprietary rights or license notices, as well as the QNX
* Development Suite License Guide at http://licensing.qnx.com/license-guide/
* for other information.
* $
*/
#include "asyncmsg_priv.h"
int asyncmsg_flush(int coid, int mode)
{
struct _asyncmsg_connect_context *acc;
struct _asyncmsg_connection_descriptor *acd;
int ret;
ret = MsgSendAsync(coid);
if (ret == -1 || mode == ASYNCMSG_FLUSH_NONBLOCK)
return ret;
if ((acc = _asyncmsg_handle(coid, _ASYNCMSG_HANDLE_LOOKUP, 0)) == NULL)
return -1;
acd = &acc->acd;
_mutex_lock(&acd->mu);
while (acd->num_curmsg) {
pthread_cond_wait(&acd->block_con, &acd->mu);
}
_mutex_unlock(&acd->mu);
return 0;
}
__SRCVERSION("asyncmsg_flush.c $Rev: 153052 $");

View File

@@ -0,0 +1,30 @@
/*
* $QNXLicenseC:
* Copyright 2007, QNX Software Systems. All Rights Reserved.
*
* You must obtain a written license from and pay applicable license fees to QNX
* Software Systems before you may reproduce, modify or distribute this software,
* or any work that includes all or part of this software. Free development
* licenses are available for evaluation and non-commercial purposes. For more
* information visit http://licensing.qnx.com or email licensing@qnx.com.
*
* This file may contain contributions from others. Please review this entire
* file for other proprietary rights or license notices, as well as the QNX
* Development Suite License Guide at http://licensing.qnx.com/license-guide/
* for other information.
* $
*/
#include <stdlib.h>
#include <sys/asyncmsg.h>
void asyncmsg_free(void *buf)
{
free(buf);
return;
}
__SRCVERSION("asyncmsg_free.c $Rev: 153052 $");

116
lib/asyncmsg/asyncmsg_get.c Normal file
View File

@@ -0,0 +1,116 @@
/*
* $QNXLicenseC:
* Copyright 2007, QNX Software Systems. All Rights Reserved.
*
* You must obtain a written license from and pay applicable license fees to QNX
* Software Systems before you may reproduce, modify or distribute this software,
* or any work that includes all or part of this software. Free development
* licenses are available for evaluation and non-commercial purposes. For more
* information visit http://licensing.qnx.com or email licensing@qnx.com.
*
* This file may contain contributions from others. Please review this entire
* file for other proprietary rights or license notices, as well as the QNX
* Development Suite License Guide at http://licensing.qnx.com/license-guide/
* for other information.
* $
*/
#include <unistd.h>
#include "asyncmsg_priv.h"
struct _asyncmsg_get_header* asyncmsg_get(int chid)
{
struct _asyncmsg_get_header *agh;
struct _asyncmsg_channel_context *acc;
iov_t *iov;
size_t entsize;
int n, used;
if ((acc = _asyncmsg_handle(chid, _ASYNCMSG_HANDLE_LOOKUP | _ASYNCMSG_HANDLE_CHANNEL, 0)) == NULL)
return NULL;
entsize = sizeof(struct _asyncmsg_get_header) + sizeof(iov_t) + acc->buffer_size;
_mutex_lock(&acc->mutex);
while (acc->num_free < acc->max_num_buffer) {
void *bufs[1];
if (!acc->recvbuf_cb) {
if ((agh = asyncmsg_malloc(entsize)) == NULL) {
break;
}
memset(agh, 0, entsize);
agh->iov = (iov_t *)(agh + 1);
agh->iov->iov_base = agh->iov + 1;
agh->iov->iov_len = acc->buffer_size;
agh->parts = 1;
agh->next = acc->free;
acc->free = agh;
acc->num_free++;
} else {
if (acc->recvbuf_cb(entsize, 1, (void **)bufs, ASYNCMSG_RECVBUF_ALLOC) <= 0) {
break;
}
agh = bufs[0];
memset(agh, 0, entsize);
agh->iov = (iov_t *)(agh + 1);
agh->iov->iov_base = agh->iov + 1;
agh->iov->iov_len = acc->buffer_size;
agh->parts = 1;
agh->next = acc->free;
acc->free = agh;
acc->num_free++;
}
}
iov = acc->iovs;
for (n = 0, agh = acc->free; n < acc->max_num_buffer && agh; n++, agh = agh->next)
{
SETIOV(&iov[n], agh, entsize);
}
if (n == 0) {
_mutex_unlock(&acc->mutex);
return NULL;
}
if (agh) {
acc->free = agh;
agh = iov[n - 1].iov_base;
agh->next = NULL;
} else {
acc->free = NULL;
}
acc->num_free -= n;
_mutex_unlock(&acc->mutex);
if ((used = MsgReceiveAsync(chid, iov, n)) <= 0) {
_mutex_lock(&acc->mutex);
agh = iov[n - 1].iov_base;
agh->next = acc->free;
acc->free = iov[0].iov_base;
acc->num_free += n;
_mutex_unlock(&acc->mutex);
return NULL;
}
if (used < n) {
_mutex_lock(&acc->mutex);
agh = iov[n - 1].iov_base;
agh->next = acc->free;
acc->free = iov[used].iov_base;
agh = iov[used - 1].iov_base;
agh->next = NULL;
acc->num_free += n - used;
_mutex_unlock(&acc->mutex);
}
agh = iov[0].iov_base;
return agh;
}
__SRCVERSION("asyncmsg_get.c $Rev: 157149 $");

View File

@@ -0,0 +1,29 @@
/*
* $QNXLicenseC:
* Copyright 2007, QNX Software Systems. All Rights Reserved.
*
* You must obtain a written license from and pay applicable license fees to QNX
* Software Systems before you may reproduce, modify or distribute this software,
* or any work that includes all or part of this software. Free development
* licenses are available for evaluation and non-commercial purposes. For more
* information visit http://licensing.qnx.com or email licensing@qnx.com.
*
* This file may contain contributions from others. Please review this entire
* file for other proprietary rights or license notices, as well as the QNX
* Development Suite License Guide at http://licensing.qnx.com/license-guide/
* for other information.
* $
*/
#include <stdlib.h>
#include <sys/asyncmsg.h>
void *asyncmsg_malloc(size_t size)
{
return malloc(size);
}
__SRCVERSION("asyncmsg_malloc.c $Rev: 153052 $");

View File

@@ -0,0 +1,59 @@
/*
* $QNXLicenseC:
* Copyright 2007, QNX Software Systems. All Rights Reserved.
*
* You must obtain a written license from and pay applicable license fees to QNX
* Software Systems before you may reproduce, modify or distribute this software,
* or any work that includes all or part of this software. Free development
* licenses are available for evaluation and non-commercial purposes. For more
* information visit http://licensing.qnx.com or email licensing@qnx.com.
*
* This file may contain contributions from others. Please review this entire
* file for other proprietary rights or license notices, as well as the QNX
* Development Suite License Guide at http://licensing.qnx.com/license-guide/
* for other information.
* $
*/
#ifndef _ASYNCMSG_PRIV_H_INCLUDED
#define _ASYNCMSG_PRIV_H_INCLUDED
#ifndef _ASYNCMSG_H_INCLUDED
#include <sys/asyncmsg.h>
#endif
#ifndef _STRING_H_INCLUDE
#include <string.h>
#endif
struct _asyncmsg_channel_context {
pthread_mutex_t mutex;
int (*recvbuf_cb)(size_t bufsize, unsigned num_bufs, void*bufs[], int flags);
int buffer_size;
int max_num_buffer;
struct _asyncmsg_get_header *free;
int num_free;
iov_t *iovs;
};
struct _asyncmsg_connect_context {
unsigned flags;
struct _asyncmsg_connection_descriptor acd;
};
#define _ASYNCMSG_CONNECT_TIMEROFF 1
/* by default, every get will try to receive 5 message */
#define _ASYNCMSG_DEFAULT_GET 5
/* for _asyncmsg_handle */
#define _ASYNCMSG_HANDLE_ADD 0
#define _ASYNCMSG_HANDLE_LOOKUP 1
#define _ASYNCMSG_HANDLE_DELETE 2
#define _ASYNCMSG_HANDLE_CHANNEL 0x80000000
extern void * _asyncmsg_handle(int id, int cmd, void *handle);
#endif

View File

@@ -0,0 +1,92 @@
/*
* $QNXLicenseC:
* Copyright 2007, QNX Software Systems. All Rights Reserved.
*
* You must obtain a written license from and pay applicable license fees to QNX
* Software Systems before you may reproduce, modify or distribute this software,
* or any work that includes all or part of this software. Free development
* licenses are available for evaluation and non-commercial purposes. For more
* information visit http://licensing.qnx.com or email licensing@qnx.com.
*
* This file may contain contributions from others. Please review this entire
* file for other proprietary rights or license notices, as well as the QNX
* Development Suite License Guide at http://licensing.qnx.com/license-guide/
* for other information.
* $
*/
#include <errno.h>
#include "asyncmsg_priv.h"
static int _asyncmsg_put_trigger(int coid, struct _asyncmsg_connect_context *acc)
{
/* figure out if we need to trigger kernel */
acc->acd.num_curmsg++;
if (acc->acd.attr.trigger_num_msg && acc->acd.num_curmsg >= acc->acd.attr.trigger_num_msg)
{
return MsgSendAsync(coid);
}
/* if this is the first message, trigger & tick the ttimer */
if (acc->flags & _ASYNCMSG_CONNECT_TIMEROFF) {
TimerSettime(acc->acd.ttimer, 0, &acc->acd.attr.trigger_time, NULL);
acc->flags &= ~_ASYNCMSG_CONNECT_TIMEROFF;
}
return 0;
}
int asyncmsg_putv(int coid, const iov_t* iov, int parts, unsigned handle, int (*call_back)(int err, void* buf, unsigned handle))
{
struct _asyncmsg_connect_context *acc;
struct _asyncmsg_connection_descriptor *acd;
struct _asyncmsg_put_header *aph;
unsigned new_tail;
int err;
if ((acc = _asyncmsg_handle(coid, _ASYNCMSG_HANDLE_LOOKUP, 0)) == NULL)
return -1;
acd = &acc->acd;
_mutex_lock(&acd->mu);
for (;;) {
new_tail = acd->sendq_tail + 1;
if (new_tail >= acd->sendq_size)
new_tail = 0;
if (new_tail != acd->sendq_free)
break;
/* put list is full */
if (acd->flags & _NTO_COF_NONBLOCK) {
_mutex_unlock(&acd->mu);
errno = EAGAIN;
return -1;
}
pthread_cond_wait(&acd->block_con, &acd->mu);
}
aph = &acd->sendq[acd->sendq_tail];
acd->sendq_tail = new_tail;
aph->err = 0;
aph->iov = (iov_t *)iov;
aph->parts = parts;
aph->handle = handle;
aph->cb = call_back;
err = _asyncmsg_put_trigger(coid, acc);
_mutex_unlock(&acd->mu);
return err;
}
int asyncmsg_put(int coid, const void *buff, size_t size, unsigned handle, int (*call_back)(int err, void* buf, unsigned handle))
{
return asyncmsg_putv(coid, (iov_t *)buff, (int)-size, handle, call_back);
}
__SRCVERSION("asyncmsg_put.c $Rev: 153052 $");

23
lib/asyncmsg/common.mk Normal file
View File

@@ -0,0 +1,23 @@
#
# Copyright 2004, QNX Software Systems Ltd. All Rights Reserved.
#
# This source code may contain confidential information of QNX Software
# Systems Ltd. (QSSL) and its licensors. Any use, reproduction,
# modification, disclosure, distribution or transfer of this software,
# or any software which includes or is based upon any of this code, is
# prohibited unless expressly authorized by QSSL by written agreement. For
# more information (including whether this source code file has been
# published) please email licensing@qnx.com.
#
ifndef QCONFIG
QCONFIG=qconfig.mk
endif
include $(QCONFIG)
define PINFO
PINFO DESCRIPTION = Asynchronous Message Passing Library
endef
INSTALLDIR=usr/lib
NAME=asyncmsg
USEFILE=
include $(MKFILES_ROOT)/qtargets.mk

View File

@@ -0,0 +1,8 @@
LIST=VARIANT
ifndef QRECURSE
QRECURSE=recurse.mk
ifdef QCONFIG
QRDIR=$(dir $(QCONFIG))
endif
endif
include $(QRDIR)$(QRECURSE)

View File

@@ -0,0 +1 @@
include ../../common.mk

View File

@@ -0,0 +1 @@
include ../../common.mk

View File

@@ -0,0 +1 @@
include ../../common.mk

View File

@@ -0,0 +1 @@
include ../../common.mk

45
lib/asyncmsg/module.tmpl Normal file
View File

@@ -0,0 +1,45 @@
<?xml version="1.0"?>
<module name="asyncmsg">
<type>Element</type>
<classification>SDK</classification>
<supports>
<availability ref="ostargets"/>
</supports>
<source available="false">
<location type="">.</location>
</source>
<GroupOwner>os</GroupOwner>
<contents>
<component id="SharedObj" generated="true">
<kind type="library"/>
<location basedir="{cpu}/so{.:endian}" runtime="true">
libasyncmsg.so
</location>
</component>
<component id="SharedArchive" generated="true">
<kind type="library"/>
<location runtime="false" basedir="{cpu}/so{.:endian}">
libasyncmsgS.a
</location>
</component>
<component id="Archive" generated="true">
<kind type="library"/>
<location basedir="{cpu}/a{.:endian}" runtime="false">
libasyncmsg.a
</location>
</component>
</contents>
<!-- Dependencies -->
<requires>
<part build="false" location="services/system"/>
</requires>
</module>

View File

@@ -0,0 +1,8 @@
LIST=VARIANT
ifndef QRECURSE
QRECURSE=recurse.mk
ifdef QCONFIG
QRDIR=$(dir $(QCONFIG))
endif
endif
include $(QRDIR)$(QRECURSE)

View File

@@ -0,0 +1 @@
include ../../common.mk

View File

@@ -0,0 +1 @@
include ../../common.mk

8
lib/asyncmsg/sh/Makefile Normal file
View File

@@ -0,0 +1,8 @@
LIST=VARIANTS
ifndef QRECURSE
QRECURSE=recurse.mk
ifdef QCONFIG
QRDIR=$(dir $(QCONFIG))
endif
endif
include $(QRDIR)$(QRECURSE)

View File

@@ -0,0 +1 @@
include ../../common.mk

View File

@@ -0,0 +1 @@
include ../../common.mk

View File

@@ -0,0 +1,8 @@
LIST=CPU
ifndef QRECURSE
QRECURSE=recurse.mk
ifdef QCONFIG
QRDIR=$(dir $(QCONFIG))
endif
endif
include $(QRDIR)$(QRECURSE)

View File

@@ -0,0 +1,127 @@
/*
* $QNXLicenseC:
* Copyright 2007, QNX Software Systems. All Rights Reserved.
*
* You must obtain a written license from and pay applicable license fees to QNX
* Software Systems before you may reproduce, modify or distribute this software,
* or any work that includes all or part of this software. Free development
* licenses are available for evaluation and non-commercial purposes. For more
* information visit http://licensing.qnx.com or email licensing@qnx.com.
*
* This file may contain contributions from others. Please review this entire
* file for other proprietary rights or license notices, as well as the QNX
* Development Suite License Guide at http://licensing.qnx.com/license-guide/
* for other information.
* $
*/
#include <stdio.h>
#include <errno.h>
#include <process.h>
#include <unistd.h>
#include <sys/asyncmsg.h>
char *msg = "AsyncMsg Passing";
int chid = -1, coid;
int getisready = 0;
void *get_thread(void *arg)
{
struct _asyncmsg_get_header *agh, *agh1;
/* async channel */
if ((chid = asyncmsg_channel_create(_NTO_CHF_SENDER_LEN, 0666, 2048, 5, NULL, NULL)) == -1) {
perror("channel_create");
return -1;
}
if ((agh = asyncmsg_get(chid)) == NULL) {
perror("get");
return NULL;
}
printf("Got message(s): \n\n");
while (agh1 = agh) {
agh = agh1->next;
printf("from process: %d (%d)\n", agh1->info.pid, getpid());
printf("msglen: %d (%d)\n", agh1->info.msglen, strlen(msg) + 1);
printf("srclen: %d\n", agh1->info.srcmsglen);
printf("err: %d\n", agh1->err);
printf("parts: %d\n", agh1->parts);
printf("msg: %s\n\n", (char *)agh1->iov->iov_base);
asyncmsg_free(agh1);
}
if (asyncmsg_channel_destroy(chid) == -1) {
perror("channel_detach");
return NULL;
}
return NULL;
}
/* The asyncmsg_get() will be blocked, and let's see if a put
* could wake it up
*/
int main(int argc, char **argv)
{
struct _asyncmsg_connection_attr aca;
int pid = 0;
if (argc > 1) {
if ((pid = fork()) == -1) {
perror("fork");
return -1;
}
if (!pid) {
get_thread(0);
return 0;
} else {
/* we lied, the parent don't know the chid in client,
* we assume it's 1 :)
*/
chid = 1;
}
} else {
if ((errno = pthread_create(0, 0, get_thread, NULL)) != EOK) {
perror("pthread_create");
return -1;
}
}
/* Let the get thread block */
sleep(1);
if (chid == -1) {
return -1;
}
memset(&aca, 0, sizeof(aca));
aca.buffer_size = 2048;
aca.max_num_buffer = 5;
aca.trigger_num_msg = 1;
if ((coid = asyncmsg_connect_attach(0, pid, chid, 0, 0, &aca)) == -1) {
perror("connect_attach");
return -1;
}
if ((asyncmsg_put(coid, msg, strlen(msg) + 1, 0, 0)) == -1) {
perror("put");
return -1;
}
sleep(1);
if (asyncmsg_connect_detach(coid) == -1) {
perror("connect_detach");
return NULL;
}
return 0;
}
__SRCVERSION("block_get.c $Rev: 153052 $");

View File

@@ -0,0 +1,98 @@
/*
* $QNXLicenseC:
* Copyright 2007, QNX Software Systems. All Rights Reserved.
*
* You must obtain a written license from and pay applicable license fees to QNX
* Software Systems before you may reproduce, modify or distribute this software,
* or any work that includes all or part of this software. Free development
* licenses are available for evaluation and non-commercial purposes. For more
* information visit http://licensing.qnx.com or email licensing@qnx.com.
*
* This file may contain contributions from others. Please review this entire
* file for other proprietary rights or license notices, as well as the QNX
* Development Suite License Guide at http://licensing.qnx.com/license-guide/
* for other information.
* $
*/
#include <stdio.h>
#include <process.h>
#include <unistd.h>
#include <sys/asyncmsg.h>
int callback(int err, void *cmsg, unsigned handle)
{
printf("Callback: err = %d, msg = %p, handle = %d\n",
err, cmsg, handle);
return 0;
}
/*
* Multiple put, then see if get could got all of them.
*/
int main()
{
int chid, coid, i;
struct _asyncmsg_connection_attr aca;
struct _asyncmsg_get_header *agh, *agh1;
char msg[3][80];
if ((chid = asyncmsg_channel_create(_NTO_CHF_SENDER_LEN, 0666, 2048, 5, NULL, NULL)) == -1) {
perror("channel_create");
return -1;
}
memset(&aca, 0, sizeof(aca));
aca.buffer_size = 2048;
aca.max_num_buffer = 5;
aca.trigger_num_msg = 3;
if ((coid = asyncmsg_connect_attach(0, 0, chid, 0, 0, &aca)) == -1) {
perror("connect_attach");
return -1;
}
for (i = 0; i < 3; i++) {
sprintf(msg[i], "Async Message Passing (msgid %d)\n", i);
if ((asyncmsg_put(coid, msg[i], strlen(msg[i]) + 1, 1234, callback)) == -1) {
perror("put");
return -1;
}
}
if ((agh = asyncmsg_get(chid)) == NULL) {
perror("get");
return -1;
}
printf("Got message(s): \n\n");
while (agh1 = agh) {
agh = agh1->next;
printf("from process: %d (%d)\n", agh1->info.pid, getpid());
printf("msglen: %d (%d)\n", agh1->info.msglen, strlen(msg) + 1);
printf("srclen: %d\n", agh1->info.srcmsglen);
printf("err: %d\n", agh1->err);
printf("parts: %d\n", agh1->parts);
printf("msg: %s\n\n", (char *)agh1->iov->iov_base);
asyncmsg_free(agh1);
}
sleep(1);
if (asyncmsg_connect_detach(coid) == -1) {
perror("connect_detach");
return -1;
}
if (asyncmsg_channel_destroy(chid) == -1) {
perror("channel_detach");
return -1;
}
return 0;
}
__SRCVERSION("bulk_put.c $Rev: 153052 $");

View File

@@ -0,0 +1,20 @@
ifndef QCONFIG
QCONFIG=qconfig.mk
endif
include $(QCONFIG)
USEFILE=
TESTS = $(basename $(notdir $(SRCS)))
INSTALLDIR=/dev/null
ICLEAN=$(TESTS)
ALL_DEPENDENCIES=$(TESTS)
LIBS += asyncmsg
EXTRA_LIBVPATH=$(PROJECT_ROOT)/../$(CPU)/a.be
include $(MKFILES_ROOT)/qtargets.mk
$(TESTS): %: %.o
$(TARGET_BUILD)

View File

@@ -0,0 +1,146 @@
/*
* $QNXLicenseC:
* Copyright 2007, QNX Software Systems. All Rights Reserved.
*
* You must obtain a written license from and pay applicable license fees to QNX
* Software Systems before you may reproduce, modify or distribute this software,
* or any work that includes all or part of this software. Free development
* licenses are available for evaluation and non-commercial purposes. For more
* information visit http://licensing.qnx.com or email licensing@qnx.com.
*
* This file may contain contributions from others. Please review this entire
* file for other proprietary rights or license notices, as well as the QNX
* Development Suite License Guide at http://licensing.qnx.com/license-guide/
* for other information.
* $
*/
#include <stdio.h>
#include <errno.h>
#include <process.h>
#include <unistd.h>
#include <sys/asyncmsg.h>
int num_callback_run = 0;
int chid;
int callback(int err, void *cmsg, unsigned handle)
{
num_callback_run++;
printf("Callback: err = %d, msg = %p, handle = %d\n",
err, cmsg, handle);
return 0;
}
void * thread_for_get(void *arg)
{
int pchid = (int)arg;
struct _pulse pulse;
struct _asyncmsg_get_header *agh, *agh1;
/* waiting for the event */
if (MsgReceivePulse(pchid, &pulse, sizeof(pulse), NULL) == -1) {
perror("MsgReceivePulse");
return NULL;
}
if ((agh = asyncmsg_get(chid)) == NULL) {
perror("get");
return NULL;
}
printf("Got message(s): \n\n");
while (agh1 = agh) {
agh = agh1->next;
printf("from process: %d (%d)\n", agh1->info.pid, getpid());
printf("msglen: %d\n", agh1->info.msglen);
printf("srclen: %d\n", agh1->info.srcmsglen);
printf("err: %d\n", agh1->err);
printf("parts: %d\n", agh1->parts);
printf("msg: %s\n\n", (char *)agh1->iov->iov_base);
asyncmsg_free(agh1);
}
return 0;
}
/*
* No trigger for put, but we force an flush(), see if all
* messages could be pushed out.
*/
int main()
{
int coid, pchid, i;
struct sigevent gev;
struct _asyncmsg_connection_attr aca;
char msg[4][80];
/* prepare the event */
if ((pchid = ChannelCreate(0)) == -1) {
perror("ChannelCreate");
return -1;
}
if ((errno = pthread_create(0, 0, thread_for_get, (void *)pchid)) != EOK)
{
perror("pthread_create");
return -1;
}
if ((gev.sigev_coid = ConnectAttach(0, 0, pchid, _NTO_SIDE_CHANNEL, 0)) == -1)
{
perror("ConnectAttach");
return -1;
}
gev.sigev_notify = SIGEV_PULSE;
gev.sigev_priority = SIGEV_PULSE_PRIO_INHERIT;
/* async channel */
if ((chid = asyncmsg_channel_create(_NTO_CHF_SENDER_LEN, 0666, 2048, 5, &gev, NULL)) == -1) {
perror("channel_create");
return -1;
}
memset(&aca, 0, sizeof(aca));
aca.buffer_size = 2048;
aca.max_num_buffer = 5;
aca.trigger_num_msg = 0;
aca.call_back = callback;
if ((coid = asyncmsg_connect_attach(0, 0, chid, 0, 0, &aca)) == -1) {
perror("connect_attach");
return -1;
}
/* put up 4 messages */
for (i = 0; i < 2; i++) {
sprintf(msg[i], "Async Message Passing (msgid %d)\n", i);
if ((asyncmsg_put(coid, msg[i], strlen(msg[i]) + 1, 1234, callback)) == -1) {
perror("put");
return -1;
}
}
asyncmsg_flush(coid, 0);
/* give the put callback a chance to run */
while (num_callback_run < 2)
delay(500);
if (asyncmsg_connect_detach(coid) == -1) {
perror("connect_detach");
return -1;
}
if (asyncmsg_channel_destroy(chid) == -1) {
perror("channel_detach");
return -1;
}
return 0;
}
__SRCVERSION("flush_put.c $Rev: 153052 $");

View File

@@ -0,0 +1,123 @@
/*
* $QNXLicenseC:
* Copyright 2007, QNX Software Systems. All Rights Reserved.
*
* You must obtain a written license from and pay applicable license fees to QNX
* Software Systems before you may reproduce, modify or distribute this software,
* or any work that includes all or part of this software. Free development
* licenses are available for evaluation and non-commercial purposes. For more
* information visit http://licensing.qnx.com or email licensing@qnx.com.
*
* This file may contain contributions from others. Please review this entire
* file for other proprietary rights or license notices, as well as the QNX
* Development Suite License Guide at http://licensing.qnx.com/license-guide/
* for other information.
* $
*/
#include <stdio.h>
#include <process.h>
#include <unistd.h>
#include <sys/asyncmsg.h>
char *msg = "AsyncMsg Passing";
int callback(int err, void *cmsg, unsigned handle)
{
printf("Callback: err = %d, msg = %p (%p), handle = %d\n",
err, cmsg, msg, handle);
return 0;
}
/*
* Simple test. Create a channel, connect to it, put a message,
* get them, done
*/
int main()
{
int chid, coid, pchid;
struct sigevent gev;
struct _pulse pulse;
struct _asyncmsg_connection_attr aca;
struct _asyncmsg_get_header *agh, *agh1;
/* prepare the event */
if ((pchid = ChannelCreate(0)) == -1) {
perror("ChannelCreate");
return -1;
}
if ((gev.sigev_coid = ConnectAttach(0, 0, pchid, _NTO_SIDE_CHANNEL, 0)) == -1)
{
perror("ConnectAttach");
return -1;
}
gev.sigev_notify = SIGEV_PULSE;
gev.sigev_priority = SIGEV_PULSE_PRIO_INHERIT;
/* async channel */
if ((chid = asyncmsg_channel_create(0, 0666, 2048, 5, &gev, NULL)) == -1) {
perror("channel_create");
return -1;
}
memset(&aca, 0, sizeof(aca));
aca.buffer_size = 2048;
aca.max_num_buffer = 5;
aca.trigger_num_msg = 1;
aca.call_back = callback;
if ((coid = asyncmsg_connect_attach(0, 0, chid, 0, 0, &aca)) == -1) {
perror("connect_attach");
return -1;
}
if ((asyncmsg_put(coid, msg, strlen(msg) + 1, 0, 0)) == -1) {
perror("put");
return -1;
}
/* waiting for the event */
if (MsgReceivePulse(pchid, &pulse, sizeof(pulse), NULL) == -1) {
perror("MsgReceivePulse");
return -1;
}
if ((agh = asyncmsg_get(chid)) == NULL) {
perror("get");
return -1;
}
printf("Got message(s): \n\n");
while (agh1 = agh) {
agh = agh1->next;
printf("from process: %d (%d)\n", agh1->info.pid, getpid());
printf("msglen: %d (%d)\n", agh1->info.msglen, strlen(msg) + 1);
printf("srclen: %d\n", agh1->info.srcmsglen);
printf("err: %d\n", agh1->err);
printf("parts: %d\n", agh1->parts);
printf("msg: %s\n\n", (char *)agh1->iov->iov_base);
asyncmsg_free(agh1);
}
/* give the callback a chance to run */
sleep(1);
if (asyncmsg_connect_detach(coid) == -1) {
perror("connect_detach");
return -1;
}
if (asyncmsg_channel_destroy(chid) == -1) {
perror("channel_detach");
return -1;
}
return 0;
}
__SRCVERSION("pulse_get.c $Rev: 153052 $");

View File

@@ -0,0 +1,98 @@
/*
* $QNXLicenseC:
* Copyright 2007, QNX Software Systems. All Rights Reserved.
*
* You must obtain a written license from and pay applicable license fees to QNX
* Software Systems before you may reproduce, modify or distribute this software,
* or any work that includes all or part of this software. Free development
* licenses are available for evaluation and non-commercial purposes. For more
* information visit http://licensing.qnx.com or email licensing@qnx.com.
*
* This file may contain contributions from others. Please review this entire
* file for other proprietary rights or license notices, as well as the QNX
* Development Suite License Guide at http://licensing.qnx.com/license-guide/
* for other information.
* $
*/
#include <stdio.h>
#include <process.h>
#include <unistd.h>
#include <sys/asyncmsg.h>
char *msg = "AsyncMsg Passing";
int callback(int err, void *cmsg, unsigned handle)
{
printf("Callback: err = %d, msg = %p (%p), handle = %d\n",
err, cmsg, msg, handle);
return 0;
}
/*
* Simple test. Create a channel, connect to it, put a message,
* get them, done
*/
int main()
{
int chid, coid;
struct _asyncmsg_connection_attr aca;
struct _asyncmsg_get_header *agh, *agh1;
if ((chid = asyncmsg_channel_create(0, 0666, 2048, 5, NULL, NULL)) == -1) {
perror("channel_create");
return -1;
}
memset(&aca, 0, sizeof(aca));
aca.buffer_size = 2048;
aca.max_num_buffer = 5;
aca.trigger_num_msg = 1;
if ((coid = asyncmsg_connect_attach(0, 0, chid, 0, 0, &aca)) == -1) {
perror("connect_attach");
return -1;
}
if ((asyncmsg_put(coid, msg, strlen(msg) + 1, 1234, callback)) == -1) {
perror("put");
return -1;
}
if ((agh = asyncmsg_get(chid)) == NULL) {
perror("get");
return -1;
}
printf("Got message(s): \n\n");
while (agh1 = agh) {
agh = agh1->next;
printf("from process: %d (%d)\n", agh1->info.pid, getpid());
printf("msglen: %d (%d)\n", agh1->info.msglen, strlen(msg) + 1);
printf("srclen: %d\n", agh1->info.srcmsglen);
printf("err: %d\n", agh1->err);
printf("parts: %d\n", agh1->parts);
printf("msg: %s\n\n", (char *)agh1->iov->iov_base);
asyncmsg_free(agh1);
}
sleep(1);
if (asyncmsg_connect_detach(coid) == -1) {
perror("connect_detach");
return -1;
}
if (asyncmsg_channel_destroy(chid) == -1) {
perror("channel_detach");
return -1;
}
return 0;
}
__SRCVERSION("put_and_get.c $Rev: 153052 $");

View File

@@ -0,0 +1,127 @@
/*
* $QNXLicenseC:
* Copyright 2007, QNX Software Systems. All Rights Reserved.
*
* You must obtain a written license from and pay applicable license fees to QNX
* Software Systems before you may reproduce, modify or distribute this software,
* or any work that includes all or part of this software. Free development
* licenses are available for evaluation and non-commercial purposes. For more
* information visit http://licensing.qnx.com or email licensing@qnx.com.
*
* This file may contain contributions from others. Please review this entire
* file for other proprietary rights or license notices, as well as the QNX
* Development Suite License Guide at http://licensing.qnx.com/license-guide/
* for other information.
* $
*/
#include <stdio.h>
#include <process.h>
#include <unistd.h>
#include <sys/asyncmsg.h>
int callback(int err, void *cmsg, unsigned handle)
{
printf("Callback: err = %d, msg = %p, handle = %d\n",
err, cmsg, handle);
return 0;
}
/*
* Set the get trigger to 2 seconds, put up 4 messages, see we could get a
* notification for get after 2 seconds.
*/
int main()
{
int chid, coid, pchid, i;
struct sigevent gev;
struct _pulse pulse;
struct _asyncmsg_connection_attr aca;
struct _asyncmsg_get_header *agh, *agh1;
char msg[4][80];
/* prepare the event */
if ((pchid = ChannelCreate(0)) == -1) {
perror("ChannelCreate");
return -1;
}
if ((gev.sigev_coid = ConnectAttach(0, 0, pchid, _NTO_SIDE_CHANNEL, 0)) == -1)
{
perror("ConnectAttach");
return -1;
}
gev.sigev_notify = SIGEV_PULSE;
gev.sigev_priority = SIGEV_PULSE_PRIO_INHERIT;
/* async channel */
if ((chid = asyncmsg_channel_create(_NTO_CHF_SENDER_LEN, 0666, 2048, 5, &gev, NULL)) == -1) {
perror("channel_create");
return -1;
}
memset(&aca, 0, sizeof(aca));
aca.buffer_size = 2048;
aca.max_num_buffer = 5;
aca.trigger_num_msg = 0;
aca.trigger_time.nsec = 2000000000L;
aca.trigger_time.interval_nsec = 0;
aca.call_back = callback;
if ((coid = asyncmsg_connect_attach(0, 0, chid, 0, 0, &aca)) == -1) {
perror("connect_attach");
return -1;
}
/* put up 4 messages */
for (i = 0; i < 4; i++) {
sprintf(msg[i], "Async Message Passing (msgid %d)\n", i);
if ((asyncmsg_put(coid, msg[i], strlen(msg[i]) + 1, 1234, callback)) == -1) {
perror("put");
return -1;
}
}
/* waiting for the event */
if (MsgReceivePulse(pchid, &pulse, sizeof(pulse), NULL) == -1) {
perror("MsgReceivePulse");
return -1;
}
if ((agh = asyncmsg_get(chid)) == NULL) {
perror("get");
return -1;
}
printf("Got message(s): \n\n");
while (agh1 = agh) {
agh = agh1->next;
printf("from process: %d (%d)\n", agh1->info.pid, getpid());
printf("msglen: %d (%d)\n", agh1->info.msglen, strlen(msg) + 1);
printf("srclen: %d\n", agh1->info.srcmsglen);
printf("err: %d\n", agh1->err);
printf("parts: %d\n", agh1->parts);
printf("msg: %s\n\n", (char *)agh1->iov->iov_base);
asyncmsg_free(agh1);
}
/* give the callback a chance to run */
sleep(1);
if (asyncmsg_connect_detach(coid) == -1) {
perror("connect_detach");
return -1;
}
if (asyncmsg_channel_destroy(chid) == -1) {
perror("channel_detach");
return -1;
}
return 0;
}
__SRCVERSION("timer_put.c $Rev: 153052 $");

View File

@@ -0,0 +1,8 @@
LIST=VARIANT
ifndef QRECURSE
QRECURSE=recurse.mk
ifdef QCONFIG
QRDIR=$(dir $(QCONFIG))
endif
endif
include $(QRDIR)$(QRECURSE)

View File

@@ -0,0 +1 @@
include ../../common.mk

View File

@@ -0,0 +1,8 @@
LIST=VARIANT
ifndef QRECURSE
QRECURSE=recurse.mk
ifdef QCONFIG
QRDIR=$(dir $(QCONFIG))
endif
endif
include $(QRDIR)$(QRECURSE)

View File

@@ -0,0 +1 @@
include ../../common.mk

View File

@@ -0,0 +1 @@
include ../../common.mk

View File

@@ -0,0 +1 @@
include ../../common.mk