static SEM_ID alloc_xsem(int options, int initval, int maxval) { int sobj_flags = 0, ret; struct wind_sem *sem; if (options & ~SEM_Q_PRIORITY) { errno = S_semLib_INVALID_OPTION; return (SEM_ID)0; } sem = alloc_sem(options, &xsem_ops); if (sem == NULL) { errno = S_memLib_NOT_ENOUGH_MEMORY; return (SEM_ID)0; } if (options & SEM_Q_PRIORITY) sobj_flags = SYNCOBJ_PRIO; sem->u.xsem.value = initval; sem->u.xsem.maxvalue = maxval; ret = syncobj_init(&sem->u.xsem.sobj, CLOCK_COPPERPLATE, sobj_flags, fnref_put(libvxworks, sem_finalize)); if (ret) { xnfree(sem); errno = S_memLib_NOT_ENOUGH_MEMORY; return (SEM_ID)0; } return mainheap_ref(sem, SEM_ID); }
/** * @fn int rt_buffer_create(RT_BUFFER *bf, const char *name, size_t bufsz, int mode) * @brief Create an IPC buffer. * * This routine creates an IPC object that allows tasks to send and * receive data asynchronously via a memory buffer. Data may be of an * arbitrary length, albeit this IPC is best suited for small to * medium-sized messages, since data always have to be copied to the * buffer during transit. Large messages may be more efficiently * handled by message queues (RT_QUEUE). * * @param bf The address of a buffer descriptor which can be later * used to identify uniquely the created object, upon success of this * call. * * @param name An ASCII string standing for the symbolic name of the * buffer. When non-NULL and non-empty, a copy of this string is used * for indexing the created buffer into the object registry. * * @param bufsz The size of the buffer space available to hold * data. The required memory is obtained from the main heap. * * @param mode The buffer creation mode. The following flags can be * OR'ed into this bitmask, each of them affecting the new buffer: * * - B_FIFO makes tasks pend in FIFO order for reading data from the * buffer. * * - B_PRIO makes tasks pend in priority order for reading data from * the buffer. * * This parameter also applies to tasks blocked on the buffer's write * side (see rt_buffer_write()). * * @return Zero is returned upon success. Otherwise: * * - -ENOMEM is returned if the system fails to get memory from the * main heap in order to create the buffer. * * - -EEXIST is returned if the @a name is conflicting with an already * registered buffer. * * - -EPERM is returned if this service was called from an * asynchronous context. * * Valid calling context: * * - Regular POSIX threads * - Xenomai threads * * @note Buffers can be shared by multiple processes which belong to * the same Xenomai session. */ int rt_buffer_create(RT_BUFFER *bf, const char *name, size_t bufsz, int mode) { struct alchemy_buffer *bcb; struct service svc; int sobj_flags = 0; int ret; if (threadobj_irq_p()) return -EPERM; if (bufsz == 0) return -EINVAL; CANCEL_DEFER(svc); bcb = xnmalloc(sizeof(*bcb)); if (bcb == NULL) { ret = __bt(-ENOMEM); goto fail; } bcb->buf = xnmalloc(bufsz); if (bcb == NULL) { ret = __bt(-ENOMEM); goto fail_bufalloc; } generate_name(bcb->name, name, &buffer_namegen); bcb->magic = buffer_magic; bcb->mode = mode; bcb->bufsz = bufsz; bcb->rdoff = 0; bcb->wroff = 0; bcb->fillsz = 0; if (mode & B_PRIO) sobj_flags = SYNCOBJ_PRIO; syncobj_init(&bcb->sobj, CLOCK_COPPERPLATE, sobj_flags, fnref_put(libalchemy, buffer_finalize)); if (syncluster_addobj(&alchemy_buffer_table, bcb->name, &bcb->cobj)) { ret = -EEXIST; goto fail_register; } bf->handle = mainheap_ref(bcb, uintptr_t); CANCEL_RESTORE(svc); return 0; fail_register: syncobj_uninit(&bcb->sobj); xnfree(bcb->buf); fail_bufalloc: xnfree(bcb); fail: CANCEL_RESTORE(svc); return ret; }