diff options
Diffstat (limited to 'cpukit/posix/src')
232 files changed, 15327 insertions, 0 deletions
diff --git a/cpukit/posix/src/.cvsignore b/cpukit/posix/src/.cvsignore new file mode 100644 index 0000000000..000074c626 --- /dev/null +++ b/cpukit/posix/src/.cvsignore @@ -0,0 +1,4 @@ +stamp-h +stamp-h.in +config.h +config.h.in diff --git a/cpukit/posix/src/README.mqueue b/cpukit/posix/src/README.mqueue new file mode 100644 index 0000000000..12c8afc03e --- /dev/null +++ b/cpukit/posix/src/README.mqueue @@ -0,0 +1,38 @@ +# +# $Id$ +# + +This program should print out the default attribute settings for a +POSIX message queue. + +#include <mqueue.h> +#include <stdio.h> + +main() +{ + mqd_t mqfd; + struct mq_attr mqstat; + int status; + + /* this should create it */ + mqfd = mq_open("myipc",O_WRONLY|O_CREAT,NULL); + if ( (int)mqfd == -1 ) { + perror( "Unable to open message queue" ); + exit( 1 ); + } + + status = mq_getattr(mqfd, &mqstat); + if ( !status ) { + printf( "mq_maxmsg: %d\n", mqstat.mq_maxmsg ); + printf( "mq_msgsize: %d\n", mqstat.mq_msgsize ); + printf( "mq_curmsgs: %d\n", mqstat.mq_curmsgs ); + } else { + perror( "Unable to get attributes on message queue" ); + exit( 1 ); + } + + /* this should delete it */ + (void) mq_close( mqfd ); + exit( 0 ); +} + diff --git a/cpukit/posix/src/_execve.c b/cpukit/posix/src/_execve.c new file mode 100644 index 0000000000..0bd8c2e7d1 --- /dev/null +++ b/cpukit/posix/src/_execve.c @@ -0,0 +1,28 @@ +/* + * execve() - POSIX 1003.1b 3.1.2 + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <errno.h> +#include <rtems/seterr.h> + +int _execve( + const char *path __attribute__((unused)), + char *const argv[] __attribute__((unused)), + char *const envp[] __attribute__((unused)) +) +{ + rtems_set_errno_and_return_minus_one( ENOSYS ); +} diff --git a/cpukit/posix/src/adjtime.c b/cpukit/posix/src/adjtime.c new file mode 100644 index 0000000000..89ccd7950d --- /dev/null +++ b/cpukit/posix/src/adjtime.c @@ -0,0 +1,104 @@ +/* + * adjime() function + * + * This method was initially added as part of porting NTP to RTEMS. + * It is a BSD compatability function and now is available on + * GNU/Linux. + */ + +/* + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <time.h> +#include <sys/time.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/config.h> +#include <rtems/seterr.h> +#include <rtems/score/tod.h> +#include <rtems/posix/time.h> +#include <rtems/score/thread.h> +#include <rtems/score/timespec.h> + +/* + * At one point there was a static variable named adjustment + * used by this implementation. I don't see any reason for it + * to be here based upon the GNU/Linux documentation. + */ + +int adjtime( + struct timeval *delta, + struct timeval *olddelta +) +{ + struct timespec ts; + long adjustment; + + /* + * Simple validations + */ + if ( !delta ) + rtems_set_errno_and_return_minus_one( EINVAL ); + + if ( delta->tv_usec >= TOD_MICROSECONDS_PER_SECOND ) + rtems_set_errno_and_return_minus_one( EINVAL ); + + if ( olddelta ) { + olddelta->tv_sec = 0; + olddelta->tv_usec = 0; + } + + /* convert delta to microseconds */ + adjustment = (delta->tv_sec * TOD_MICROSECONDS_PER_SECOND); + adjustment += delta->tv_usec; + + /* too small to account for */ + if ( adjustment < rtems_configuration_get_microseconds_per_tick() ) + return 0; + + /* + * This prevents context switches while we are adjusting the TOD + */ + + _Thread_Disable_dispatch(); + + _TOD_Get( &ts ); + + ts.tv_sec += delta->tv_sec; + ts.tv_nsec += delta->tv_usec * TOD_NANOSECONDS_PER_MICROSECOND; + + /* if adjustment is too much positive */ + while ( ts.tv_nsec >= TOD_NANOSECONDS_PER_SECOND ) { + ts.tv_nsec -= TOD_NANOSECONDS_PER_SECOND; + ts.tv_sec++; + } + + /* if adjustment is too much negative */ + while ( ts.tv_nsec <= (-1 * TOD_NANOSECONDS_PER_SECOND) ) { + ts.tv_nsec += TOD_NANOSECONDS_PER_SECOND; + ts.tv_sec--; + } + + _TOD_Set( &ts ); + + _Thread_Enable_dispatch(); + + /* set the user's output */ + if ( olddelta ) + *olddelta = *delta; + + return 0; +} diff --git a/cpukit/posix/src/aio_cancel.c b/cpukit/posix/src/aio_cancel.c new file mode 100644 index 0000000000..56b7b01079 --- /dev/null +++ b/cpukit/posix/src/aio_cancel.c @@ -0,0 +1,126 @@ +/* + * Copyright 2010, Alin Rus <alin.codejunkie@gmail.com> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <aio.h> +#include <rtems/posix/aio_misc.h> +#include <errno.h> +#include <stdlib.h> +#include <rtems/system.h> +#include <rtems/seterr.h> + +/* + * aio_cancel + * + * Cancel an asynchronous I/O request + * + * Input parameters: + * fildes - file descriptor + * aiocbp - asynchronous I/O control block + * + * Output parameters: + * AIO_CANCELED - if the requested operation(s) + * were canceled + * AIO_NOTCANCELED - if at least one of the requested + * operation(s) cannot be canceled + */ + + +int aio_cancel(int fildes, struct aiocb *aiocbp) +{ + rtems_aio_request_chain *r_chain; + int result; + + pthread_mutex_lock (&aio_request_queue.mutex); + + if (fcntl (fildes, F_GETFD) < 0) { + pthread_mutex_unlock(&aio_request_queue.mutex); + rtems_set_errno_and_return_minus_one (EBADF); + } + + /* if aiocbp is NULL remove all request for given file descriptor */ + if (aiocbp == NULL) { + AIO_printf ("Cancel all requests\n"); + + r_chain = rtems_aio_search_fd (&aio_request_queue.work_req, fildes, 0); + if (r_chain == NULL) { + AIO_printf ("Request chain not on [WQ]\n"); + + if (!rtems_chain_is_empty (&aio_request_queue.idle_req)) { + r_chain = rtems_aio_search_fd (&aio_request_queue.idle_req, fildes, 0); + if (r_chain == NULL) { + pthread_mutex_unlock(&aio_request_queue.mutex); + return AIO_ALLDONE; + } + + AIO_printf ("Request chain on [IQ]\n"); + + rtems_chain_extract (&r_chain->next_fd); + rtems_aio_remove_fd (r_chain); + pthread_mutex_destroy (&r_chain->mutex); + pthread_cond_destroy (&r_chain->mutex); + free (r_chain); + + pthread_mutex_unlock (&aio_request_queue.mutex); + return AIO_CANCELED; + } + + pthread_mutex_unlock (&aio_request_queue.mutex); + return AIO_ALLDONE; + } + + AIO_printf ("Request chain on [WQ]\n"); + + pthread_mutex_lock (&r_chain->mutex); + rtems_chain_extract (&r_chain->next_fd); + rtems_aio_remove_fd (r_chain); + pthread_mutex_unlock (&r_chain->mutex); + pthread_mutex_unlock (&aio_request_queue.mutex); + return AIO_CANCELED; + } else { + AIO_printf ("Cancel request\n"); + + if (aiocbp->aio_fildes != fildes) { + pthread_mutex_unlock (&aio_request_queue.mutex); + rtems_set_errno_and_return_minus_one (EINVAL); + } + + r_chain = rtems_aio_search_fd (&aio_request_queue.work_req, fildes, 0); + if (r_chain == NULL) { + if (!rtems_chain_is_empty (&aio_request_queue.idle_req)) { + r_chain = rtems_aio_search_fd (&aio_request_queue.idle_req, fildes, 0); + if (r_chain == NULL) { + pthread_mutex_unlock (&aio_request_queue.mutex); + rtems_set_errno_and_return_minus_one (EINVAL); + } + + AIO_printf ("Request on [IQ]\n"); + + result = rtems_aio_remove_req (&r_chain->perfd, aiocbp); + pthread_mutex_unlock (&aio_request_queue.mutex); + return result; + } else { + pthread_mutex_unlock (&aio_request_queue.mutex); + return AIO_ALLDONE; + } + } + AIO_printf ("Request on [WQ]\n"); + + pthread_mutex_lock (&r_chain->mutex); + result = rtems_aio_remove_req (&r_chain->perfd, aiocbp); + pthread_mutex_unlock (&r_chain->mutex); + pthread_mutex_unlock (&aio_request_queue.mutex); + return result; + } + return AIO_ALLDONE; +} diff --git a/cpukit/posix/src/aio_error.c b/cpukit/posix/src/aio_error.c new file mode 100644 index 0000000000..1c0e582bc9 --- /dev/null +++ b/cpukit/posix/src/aio_error.c @@ -0,0 +1,38 @@ +/* + * Copyright 2010, Alin Rus <alin.codejunkie@gmail.com> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <aio.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/seterr.h> + +/* + * aio_error + * + * Retrieve errors status for an asynchronous I/O operation + * + * Input parameters: + * aiocbp - asynchronous I/O control block + * + * Output parameters: + * aiocbp->error_code + */ + + +int +aio_error (const struct aiocb *aiocbp) +{ + return aiocbp->error_code; +} diff --git a/cpukit/posix/src/aio_fsync.c b/cpukit/posix/src/aio_fsync.c new file mode 100644 index 0000000000..4a28b194b5 --- /dev/null +++ b/cpukit/posix/src/aio_fsync.c @@ -0,0 +1,63 @@ +/* + * Copyright 2010, Alin Rus <alin.codejunkie@gmail.com> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <aio.h> +#include <errno.h> +#include <stdlib.h> +#include <rtems/posix/aio_misc.h> +#include <rtems/system.h> +#include <rtems/seterr.h> + +/* + * aio_fsync + * + * Asynchronous file synchronization + * + * Input parameters: + * op - O_SYNC + * aiocbp - asynchronous I/O control block + * + * Output parameters: + * -1 - request could not pe enqueued + * - FD not opened for write + * - not enough memory + * - op is not O_SYNC + * 0 - otherwise + */ + +int aio_fsync( + int op, + struct aiocb *aiocbp +) +{ + rtems_aio_request *req; + int mode; + + if (op != O_SYNC) + rtems_aio_set_errno_return_minus_one (EINVAL, aiocbp); + + mode = fcntl (aiocbp->aio_fildes, F_GETFL); + if (!(((mode & O_ACCMODE) == O_WRONLY) || ((mode & O_ACCMODE) == O_RDWR))) + rtems_aio_set_errno_return_minus_one (EBADF, aiocbp); + + req = malloc (sizeof (rtems_aio_request)); + if (req == NULL) + rtems_aio_set_errno_return_minus_one (EAGAIN, aiocbp); + + req->aiocbp = aiocbp; + req->aiocbp->aio_lio_opcode = LIO_SYNC; + + return rtems_aio_enqueue (req); + +} diff --git a/cpukit/posix/src/aio_misc.c b/cpukit/posix/src/aio_misc.c new file mode 100644 index 0000000000..fa731b8d90 --- /dev/null +++ b/cpukit/posix/src/aio_misc.c @@ -0,0 +1,556 @@ +/* + * Copyright 2010-2011, Alin Rus <alin.codejunkie@gmail.com> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#include <pthread.h> +#include <stdlib.h> +#include <unistd.h> +#include <time.h> +#include <rtems/posix/aio_misc.h> +#include <errno.h> + +static void *rtems_aio_handle (void *arg); + +rtems_aio_queue aio_request_queue; + +/* + * rtems_aio_init + * + * Initialize the request queue for aio + * + * Input parameters: + * NONE + * + * Output parameters: + * 0 - if initialization succeeded + */ + +int +rtems_aio_init (void) +{ + int result = 0; + + result = pthread_attr_init (&aio_request_queue.attr); + if (result != 0) + return result; + + result = + pthread_attr_setdetachstate (&aio_request_queue.attr, + PTHREAD_CREATE_DETACHED); + if (result != 0) + pthread_attr_destroy (&aio_request_queue.attr); + + + result = pthread_mutex_init (&aio_request_queue.mutex, NULL); + if (result != 0) + pthread_attr_destroy (&aio_request_queue.attr); + + + result = pthread_cond_init (&aio_request_queue.new_req, NULL); + if (result != 0) { + pthread_mutex_destroy (&aio_request_queue.mutex); + pthread_attr_destroy (&aio_request_queue.attr); + } + + rtems_chain_initialize_empty (&aio_request_queue.work_req); + rtems_chain_initialize_empty (&aio_request_queue.idle_req); + + aio_request_queue.active_threads = 0; + aio_request_queue.idle_threads = 0; + aio_request_queue.initialized = AIO_QUEUE_INITIALIZED; + + return result; +} + +/* + * rtems_aio_search_fd + * + * Search and create chain of requests for given FD + * + * Input parameters: + * chain - chain of FD chains + * fildes - file descriptor to search + * create - if 1 search and create + * - if 0 just search + * + * Output parameters: + * r_chain - NULL if create == 0 and there is + * no chain for given fildes + * - pointer to chain is there exists + * a chain for given fildes + * - pointer to newly create chain if + * create == 1 + * + */ + +rtems_aio_request_chain * +rtems_aio_search_fd (rtems_chain_control *chain, int fildes, int create) +{ + rtems_aio_request_chain *r_chain; + rtems_chain_node *node; + + node = rtems_chain_first (chain); + r_chain = (rtems_aio_request_chain *) node; + + while (r_chain->fildes < fildes && !rtems_chain_is_tail (chain, node)) { + node = rtems_chain_next (node); + r_chain = (rtems_aio_request_chain *) node; + } + + if (r_chain->fildes == fildes) + r_chain->new_fd = 0; + else { + if (create == 0) + r_chain = NULL; + else { + r_chain = malloc (sizeof (rtems_aio_request_chain)); + rtems_chain_initialize_empty (&r_chain->perfd); + + if (rtems_chain_is_empty (chain)) + rtems_chain_prepend (chain, &r_chain->next_fd); + else + rtems_chain_insert (rtems_chain_previous (node), &r_chain->next_fd); + + r_chain->new_fd = 1; + r_chain->fildes = fildes; + } + } + return r_chain; +} + +/* + * rtems_aio_move_to_work + * + * Move chain of requests from IQ to WQ + * + * Input parameters: + * r_chain - chain of requests + * + * Output paramteres: + * NONE + */ + +void +rtems_aio_move_to_work (rtems_aio_request_chain *r_chain) +{ + rtems_aio_request_chain *temp; + rtems_chain_node *node; + + node = rtems_chain_first (&aio_request_queue.work_req); + temp = (rtems_aio_request_chain *) node; + + while (temp->fildes < r_chain->fildes && + !rtems_chain_is_tail (&aio_request_queue.work_req, node)) { + node = rtems_chain_next (node); + temp = (rtems_aio_request_chain *) node; + } + + rtems_chain_insert (rtems_chain_previous (node), &r_chain->next_fd); +} + + +/* + * rtems_aio_insert_prio + * + * Add request to given FD chain. The chain is ordered + * by priority + * + * Input parameters: + * chain - chain of requests for a given FD + * req - request (see aio_misc.h) + * + * Output parameters: + * NONE + */ + +void +rtems_aio_insert_prio (rtems_chain_control *chain, rtems_aio_request *req) +{ + rtems_chain_node *node; + + AIO_printf ("FD exists \n"); + node = rtems_chain_first (chain); + + if (rtems_chain_is_empty (chain)) { + AIO_printf ("First in chain \n"); + rtems_chain_prepend (chain, &req->next_prio); + } else { + AIO_printf ("Add by priority \n"); + int prio = ((rtems_aio_request *) node)->aiocbp->aio_reqprio; + + while (req->aiocbp->aio_reqprio > prio && + !rtems_chain_is_tail (chain, node)) { + node = rtems_chain_next (node); + prio = ((rtems_aio_request *) node)->aiocbp->aio_reqprio; + } + + rtems_chain_insert (node->previous, &req->next_prio); + + } +} + +/* + * rtems_aio_remove_fd + * + * Removes all the requests in a fd chain + * + * Input parameters: + * r_chain - pointer to the fd chain request + * + * Output parameters: + * NONE + */ + +void rtems_aio_remove_fd (rtems_aio_request_chain *r_chain) +{ + rtems_chain_control *chain; + rtems_chain_node *node; + chain = &r_chain->perfd; + node = rtems_chain_first (chain); + + while (!rtems_chain_is_tail (chain, node)) + { + rtems_chain_extract (node); + rtems_aio_request *req = (rtems_aio_request *) node; + node = rtems_chain_next (node); + req->aiocbp->error_code = ECANCELED; + req->aiocbp->return_value = -1; + free (req); + } +} + +/* + * rtems_aio_remove_req + * + * Removes request from given chain + * + * Input parameters: + * chain - pointer to fd chain which may contain + * the request + * aiocbp - pointer to request that needs to be + * canceled + * + * Output parameters: + * AIO_NOTCANCELED - if request was not canceled + * AIO_CANCELED - if request was canceled + */ + +int rtems_aio_remove_req (rtems_chain_control *chain, struct aiocb *aiocbp) +{ + if (rtems_chain_is_empty (chain)) + return AIO_ALLDONE; + + rtems_chain_node *node = rtems_chain_first (chain); + rtems_aio_request *current; + + current = (rtems_aio_request *) node; + + while (!rtems_chain_is_tail (chain, node) && current->aiocbp != aiocbp) { + node = rtems_chain_next (node); + current = (rtems_aio_request *) node; + } + + if (rtems_chain_is_tail (chain, node)) + return AIO_NOTCANCELED; + else + { + rtems_chain_extract (node); + current->aiocbp->error_code = ECANCELED; + current->aiocbp->return_value = -1; + free (current); + } + + return AIO_CANCELED; +} + +/* + * rtems_aio_enqueue + * + * Enqueue requests, and creates threads to process them + * + * Input parameters: + * req - see aio_misc.h + * + * Output parameters: + * 0 - if request was added to queue + * errno - otherwise + */ + +int +rtems_aio_enqueue (rtems_aio_request *req) +{ + + rtems_aio_request_chain *r_chain; + rtems_chain_control *chain; + pthread_t thid; + int result, policy; + struct sched_param param; + + /* The queue should be initialized */ + AIO_assert (aio_request_queue.initialized == AIO_QUEUE_INITIALIZED); + + result = pthread_mutex_lock (&aio_request_queue.mutex); + if (result != 0) { + free (req); + return result; + } + + /* _POSIX_PRIORITIZED_IO and _POSIX_PRIORITY_SCHEDULING are defined, + we can use aio_reqprio to lower the priority of the request */ + pthread_getschedparam (pthread_self(), &policy, ¶m); + + req->caller_thread = pthread_self (); + req->priority = param.sched_priority - req->aiocbp->aio_reqprio; + req->policy = policy; + req->aiocbp->error_code = EINPROGRESS; + req->aiocbp->return_value = 0; + + if ((aio_request_queue.idle_threads == 0) && + aio_request_queue.active_threads < AIO_MAX_THREADS) + /* we still have empty places on the active_threads chain */ + { + chain = &aio_request_queue.work_req; + r_chain = rtems_aio_search_fd (chain, req->aiocbp->aio_fildes, 1); + + if (r_chain->new_fd == 1) { + rtems_chain_prepend (&r_chain->perfd, &req->next_prio); + r_chain->new_fd = 0; + pthread_mutex_init (&r_chain->mutex, NULL); + pthread_cond_init (&r_chain->cond, NULL); + + AIO_printf ("New thread \n"); + result = pthread_create (&thid, &aio_request_queue.attr, + rtems_aio_handle, (void *) r_chain); + if (result != 0) { + pthread_mutex_unlock (&aio_request_queue.mutex); + return result; + } + ++aio_request_queue.active_threads; + } + else { + /* put request in the fd chain it belongs to */ + pthread_mutex_lock (&r_chain->mutex); + rtems_aio_insert_prio (&r_chain->perfd, req); + pthread_cond_signal (&r_chain->cond); + pthread_mutex_unlock (&r_chain->mutex); + } + } + else + { + /* the maximum number of threads has been already created + even though some of them might be idle. + The request belongs to one of the active fd chain */ + r_chain = rtems_aio_search_fd (&aio_request_queue.work_req, + req->aiocbp->aio_fildes, 0); + if (r_chain != NULL) + { + pthread_mutex_lock (&r_chain->mutex); + rtems_aio_insert_prio (&r_chain->perfd, req); + pthread_cond_signal (&r_chain->cond); + pthread_mutex_unlock (&r_chain->mutex); + + } else { + + /* or to the idle chain */ + chain = &aio_request_queue.idle_req; + r_chain = rtems_aio_search_fd (chain, req->aiocbp->aio_fildes, 1); + + if (r_chain->new_fd == 1) { + /* If this is a new fd chain we signal the idle threads that + might be waiting for requests */ + AIO_printf (" New chain on waiting queue \n "); + rtems_chain_prepend (&r_chain->perfd, &req->next_prio); + r_chain->new_fd = 0; + pthread_mutex_init (&r_chain->mutex, NULL); + pthread_cond_init (&r_chain->cond, NULL); + } else + /* just insert the request in the existing fd chain */ + rtems_aio_insert_prio (&r_chain->perfd, req); + if (aio_request_queue.idle_threads > 0) + pthread_cond_signal (&aio_request_queue.new_req); + } + } + + pthread_mutex_unlock (&aio_request_queue.mutex); + return 0; +} + +/* + * rtems_aio_handle + * + * Thread processing requests + * + * Input parameters: + * arg - the chain for the fd to be worked on + * + * Output parameters: + * NULL - if error + */ + +static void * +rtems_aio_handle (void *arg) +{ + + rtems_aio_request_chain *r_chain = arg; + rtems_aio_request *req; + rtems_chain_control *chain; + rtems_chain_node *node; + int result, policy; + struct sched_param param; + + AIO_printf ("Thread started\n"); + + while (1) { + + /* acquire the mutex of the current fd chain. + we don't need to lock the queue mutex since we can + add requests to idle fd chains or even active ones + if the working request has been extracted from the + chain */ + result = pthread_mutex_lock (&r_chain->mutex); + if (result != 0) + return NULL; + + chain = &r_chain->perfd; + + /* If the locked chain is not empty, take the first + request extract it, unlock the chain and process + the request, in this way the user can supply more + requests to this fd chain */ + if (!rtems_chain_is_empty (chain)) { + + AIO_printf ("Get new request from not empty chain\n"); + node = rtems_chain_first (chain); + req = (rtems_aio_request *) node; + + /* See _POSIX_PRIORITIZE_IO and _POSIX_PRIORITY_SCHEDULING + discussion in rtems_aio_enqueue () */ + pthread_getschedparam (pthread_self(), &policy, ¶m); + param.sched_priority = req->priority; + pthread_setschedparam (pthread_self(), req->policy, ¶m); + + rtems_chain_extract (node); + + pthread_mutex_unlock (&r_chain->mutex); + + switch (req->aiocbp->aio_lio_opcode) { + case LIO_READ: + AIO_printf ("read\n"); + result = pread (req->aiocbp->aio_fildes, + (void *) req->aiocbp->aio_buf, + req->aiocbp->aio_nbytes, req->aiocbp->aio_offset); + break; + + case LIO_WRITE: + AIO_printf ("write\n"); + result = pwrite (req->aiocbp->aio_fildes, + (void *) req->aiocbp->aio_buf, + req->aiocbp->aio_nbytes, req->aiocbp->aio_offset); + break; + + case LIO_SYNC: + AIO_printf ("sync\n"); + result = fsync (req->aiocbp->aio_fildes); + break; + + default: + result = -1; + } + if (result == -1) { + req->aiocbp->return_value = -1; + req->aiocbp->error_code = errno; + } else { + req->aiocbp->return_value = result; + req->aiocbp->error_code = 0; + } + + // notification needed for lio + + } else { + /* If the fd chain is empty we unlock the fd chain + and we lock the queue chain, this will ensure that + we have at most one request comming to our fd chain + when we check. + + If there was no request added sleep for 3 seconds and + wait for a signal on chain, this will unlock the queue. + The fd chain is already unlocked */ + + struct timespec timeout; + + AIO_printf ("Chain is empty [WQ], wait for work\n"); + + pthread_mutex_unlock (&r_chain->mutex); + pthread_mutex_lock (&aio_request_queue.mutex); + + if (rtems_chain_is_empty (chain)) + { + clock_gettime (CLOCK_REALTIME, &timeout); + timeout.tv_sec += 3; + timeout.tv_nsec = 0; + result = pthread_cond_timedwait (&r_chain->cond, + &aio_request_queue.mutex, + &timeout); + + /* If no requests were added to the chain we delete the fd chain from + the queue and start working with idle fd chains */ + if (result == ETIMEDOUT) { + rtems_chain_extract (&r_chain->next_fd); + pthread_mutex_destroy (&r_chain->mutex); + pthread_cond_destroy (&r_chain->cond); + free (r_chain); + + /* If the idle chain is empty sleep for 3 seconds and wait for a + signal. The thread now becomes idle. */ + if (rtems_chain_is_empty (&aio_request_queue.idle_req)) { + AIO_printf ("Chain is empty [IQ], wait for work\n"); + + ++aio_request_queue.idle_threads; + --aio_request_queue.active_threads; + clock_gettime (CLOCK_REALTIME, &timeout); + timeout.tv_sec += 3; + timeout.tv_nsec = 0; + + result = pthread_cond_timedwait (&aio_request_queue.new_req, + &aio_request_queue.mutex, + &timeout); + + /* If no new fd chain was added in the idle requests + then this thread is finished */ + if (result == ETIMEDOUT) { + AIO_printf ("Etimeout\n"); + --aio_request_queue.idle_threads; + pthread_mutex_unlock (&aio_request_queue.mutex); + return NULL; + } + } + /* Otherwise move this chain to the working chain and + start the loop all over again */ + AIO_printf ("Work on idle\n"); + --aio_request_queue.idle_threads; + ++aio_request_queue.active_threads; + + node = rtems_chain_first (&aio_request_queue.idle_req); + rtems_chain_extract (node); + + r_chain = (rtems_aio_request_chain *) node; + rtems_aio_move_to_work (r_chain); + + } + } + /* If there was a request added in the initial fd chain then release + the mutex and process it */ + pthread_mutex_unlock (&aio_request_queue.mutex); + + } + } + + AIO_printf ("Thread finished\n"); + return NULL; +} diff --git a/cpukit/posix/src/aio_read.c b/cpukit/posix/src/aio_read.c new file mode 100644 index 0000000000..43536fff74 --- /dev/null +++ b/cpukit/posix/src/aio_read.c @@ -0,0 +1,65 @@ +/* + * Copyright 2010, Alin Rus <alin.codejunkie@gmail.com> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <aio.h> +#include <errno.h> +#include <fcntl.h> +#include <rtems/posix/aio_misc.h> +#include <rtems/system.h> +#include <rtems/seterr.h> +#include <stdlib.h> + +/* + * aio_read + * + * Asynchronous write to a file + * + * Input parameters: + * aiocbp - asynchronous I/O control block + * + * Output parameters: + * -1 - request could not pe enqueued + * - FD not opened for write + * - invalid aio_reqprio or aio_offset or + * aio_nbytes + * - not enough memory + * 0 - otherwise + */ + +int +aio_read (struct aiocb *aiocbp) +{ + rtems_aio_request *req; + int mode; + + mode = fcntl (aiocbp->aio_fildes, F_GETFL); + if (!(((mode & O_ACCMODE) == O_RDONLY) || ((mode & O_ACCMODE) == O_RDWR))) + rtems_aio_set_errno_return_minus_one (EBADF, aiocbp); + + if (aiocbp->aio_reqprio < 0 || aiocbp->aio_reqprio > AIO_PRIO_DELTA_MAX) + rtems_aio_set_errno_return_minus_one (EINVAL, aiocbp); + + if (aiocbp->aio_offset < 0) + rtems_aio_set_errno_return_minus_one (EINVAL, aiocbp); + + req = malloc (sizeof (rtems_aio_request)); + if (req == NULL) + rtems_aio_set_errno_return_minus_one (EAGAIN, aiocbp); + + req->aiocbp = aiocbp; + req->aiocbp->aio_lio_opcode = LIO_READ; + + return rtems_aio_enqueue (req); +} diff --git a/cpukit/posix/src/aio_return.c b/cpukit/posix/src/aio_return.c new file mode 100644 index 0000000000..2a9e56ae7a --- /dev/null +++ b/cpukit/posix/src/aio_return.c @@ -0,0 +1,37 @@ +/* + * Copyright 2010, Alin Rus <alin.codejunkie@gmail.com> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <aio.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/seterr.h> + +/* + * aio_return + * + * Retrieve return status of an asynchronous I/O operation + * + * Input parameters: + * aiocbp - asynchronous I/O control block + * + * Output parameters: + * aiocbp->return_value + */ + +ssize_t +aio_return (const struct aiocb *aiocbp) +{ + return aiocbp->return_value; +} diff --git a/cpukit/posix/src/aio_suspend.c b/cpukit/posix/src/aio_suspend.c new file mode 100644 index 0000000000..28ed3565e5 --- /dev/null +++ b/cpukit/posix/src/aio_suspend.c @@ -0,0 +1,31 @@ +/* + * 6.7.7 Wait for Asynchronous I/O Request, P1003.1b-1993, p. 164 + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <aio.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/seterr.h> + +int aio_suspend( + const struct aiocb * const list[] __attribute__((unused)), + int nent __attribute__((unused)), + const struct timespec *timeout __attribute__((unused)) +) +{ + rtems_set_errno_and_return_minus_one( ENOSYS ); +} diff --git a/cpukit/posix/src/aio_write.c b/cpukit/posix/src/aio_write.c new file mode 100644 index 0000000000..03f6b90c64 --- /dev/null +++ b/cpukit/posix/src/aio_write.c @@ -0,0 +1,65 @@ +/* + * Copyright 2010, Alin Rus <alin.codejunkie@gmail.com> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <aio.h> +#include <errno.h> +#include <fcntl.h> +#include <rtems/posix/aio_misc.h> +#include <rtems/system.h> +#include <rtems/seterr.h> +#include <stdlib.h> + +/* + * aio_write + * + * Asynchronous write to a file + * + * Input parameters: + * aiocbp - asynchronous I/O control block + * + * Output parameters: + * -1 - request could not be enqueued + * - FD not opened for write + * - invalid aio_reqprio or aio_offset or + * aio_nbytes + * - not enough memory + * 0 - otherwise + */ + +int +aio_write (struct aiocb *aiocbp) +{ + rtems_aio_request *req; + int mode; + + mode = fcntl (aiocbp->aio_fildes, F_GETFL); + if (!(((mode & O_ACCMODE) == O_WRONLY) || ((mode & O_ACCMODE) == O_RDWR))) + rtems_aio_set_errno_return_minus_one (EBADF, aiocbp); + + if (aiocbp->aio_reqprio < 0 || aiocbp->aio_reqprio > AIO_PRIO_DELTA_MAX) + rtems_aio_set_errno_return_minus_one (EINVAL, aiocbp); + + if (aiocbp->aio_offset < 0) + rtems_aio_set_errno_return_minus_one (EINVAL, aiocbp); + + req = malloc (sizeof (rtems_aio_request)); + if (req == NULL) + rtems_aio_set_errno_return_minus_one (EAGAIN, aiocbp); + + req->aiocbp = aiocbp; + req->aiocbp->aio_lio_opcode = LIO_WRITE; + + return rtems_aio_enqueue (req); +} diff --git a/cpukit/posix/src/alarm.c b/cpukit/posix/src/alarm.c new file mode 100644 index 0000000000..ec381878a5 --- /dev/null +++ b/cpukit/posix/src/alarm.c @@ -0,0 +1,76 @@ +/* + * 3.4.1 Schedule Alarm, P1003.1b-1993, p. 79 + */ + +/* COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> + +#include <rtems/system.h> +#include <rtems/posix/pthread.h> +#include <rtems/posix/psignal.h> + +/*PAGE + * + * _POSIX_signals_Alarm_TSR + */ + +void _POSIX_signals_Alarm_TSR( + Objects_Id id __attribute__((unused)), + void *argument __attribute__((unused)) +) +{ + int status; + + status = kill( getpid(), SIGALRM ); + /* XXX can't print from an ISR, should this be fatal? */ +} + +unsigned int alarm( + unsigned int seconds +) +{ + unsigned int remaining = 0; + Watchdog_Control *the_timer; + + the_timer = &_POSIX_signals_Alarm_timer; + + /* + * Initialize the timer used to implement alarm(). + */ + + if ( !the_timer->routine ) { + _Watchdog_Initialize( the_timer, _POSIX_signals_Alarm_TSR, 0, NULL ); + } else { + Watchdog_States state; + + state = _Watchdog_Remove( the_timer ); + if ( (state == WATCHDOG_ACTIVE) || (state == WATCHDOG_REMOVE_IT) ) { + /* + * The stop_time and start_time fields are snapshots of ticks since + * boot. Since alarm() is dealing in seconds, we must account for + * this. + */ + + remaining = the_timer->initial - + ((the_timer->stop_time - the_timer->start_time) / TOD_TICKS_PER_SECOND); + } + } + + if ( seconds ) + _Watchdog_Insert_seconds( the_timer, seconds ); + + return remaining; +} diff --git a/cpukit/posix/src/barrierattrdestroy.c b/cpukit/posix/src/barrierattrdestroy.c new file mode 100644 index 0000000000..8821866af9 --- /dev/null +++ b/cpukit/posix/src/barrierattrdestroy.c @@ -0,0 +1,41 @@ +/* + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/score/object.h> +#include <rtems/score/states.h> +#include <rtems/score/watchdog.h> +#include <rtems/posix/cond.h> +#include <rtems/posix/time.h> +#include <rtems/posix/mutex.h> + +/*PAGE + * + * Barrier Initialization Attributes + */ + +int pthread_barrierattr_destroy( + pthread_barrierattr_t *attr +) +{ + if ( !attr || attr->is_initialized == false ) + return EINVAL; + + attr->is_initialized = false; + return 0; +} diff --git a/cpukit/posix/src/barrierattrgetpshared.c b/cpukit/posix/src/barrierattrgetpshared.c new file mode 100644 index 0000000000..0d8d7f1d33 --- /dev/null +++ b/cpukit/posix/src/barrierattrgetpshared.c @@ -0,0 +1,37 @@ +/* + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +/*PAGE + * + * Barrier Attributes Get Process Shared + */ + +int pthread_barrierattr_getpshared( + const pthread_barrierattr_t *attr, + int *pshared +) +{ + if ( !attr ) + return EINVAL; + + if ( !attr->is_initialized ) + return EINVAL; + + *pshared = attr->process_shared; + return 0; +} diff --git a/cpukit/posix/src/barrierattrinit.c b/cpukit/posix/src/barrierattrinit.c new file mode 100644 index 0000000000..b1a6e980c9 --- /dev/null +++ b/cpukit/posix/src/barrierattrinit.c @@ -0,0 +1,36 @@ +/* + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> + +/*PAGE + * + * Barrier Attributes Initialization + */ + +int pthread_barrierattr_init( + pthread_barrierattr_t *attr +) +{ + if ( !attr ) + return EINVAL; + + attr->is_initialized = true; + attr->process_shared = PTHREAD_PROCESS_PRIVATE; + return 0; +} diff --git a/cpukit/posix/src/barrierattrsetpshared.c b/cpukit/posix/src/barrierattrsetpshared.c new file mode 100644 index 0000000000..a899bb91c2 --- /dev/null +++ b/cpukit/posix/src/barrierattrsetpshared.c @@ -0,0 +1,44 @@ +/* + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +/*PAGE + * + * Barrier Attributes Set Process Shared + */ + +int pthread_barrierattr_setpshared( + pthread_barrierattr_t *attr, + int pshared +) +{ + if ( !attr ) + return EINVAL; + + if ( !attr->is_initialized ) + return EINVAL; + + switch ( pshared ) { + case PTHREAD_PROCESS_SHARED: + case PTHREAD_PROCESS_PRIVATE: + attr->process_shared = pshared; + return 0; + + default: + return EINVAL; + } +} diff --git a/cpukit/posix/src/cancel.c b/cpukit/posix/src/cancel.c new file mode 100644 index 0000000000..0167c0a328 --- /dev/null +++ b/cpukit/posix/src/cancel.c @@ -0,0 +1,67 @@ +/* + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/score/chain.h> +#include <rtems/score/isr.h> +#include <rtems/score/thread.h> +#include <rtems/score/wkspace.h> +#include <rtems/posix/cancel.h> +#include <rtems/posix/pthread.h> +#include <rtems/posix/threadsup.h> + +/* + * 18.2.1 Canceling Execution of a Thread, P1003.1c/Draft 10, p. 181 + */ + +int pthread_cancel( + pthread_t thread +) +{ + Thread_Control *the_thread; + POSIX_API_Control *thread_support; + Objects_Locations location; + + /* + * Don't even think about deleting a resource from an ISR. + */ + + if ( _ISR_Is_in_progress() ) + return EPROTO; + + the_thread = _Thread_Get( thread, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + thread_support = the_thread->API_Extensions[ THREAD_API_POSIX ]; + + thread_support->cancelation_requested = 1; + + /* This enables dispatch implicitly */ + _POSIX_Thread_Evaluate_cancellation_and_enable_dispatch( the_thread ); + return 0; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: +#endif + case OBJECTS_ERROR: + break; + } + + return EINVAL; +} diff --git a/cpukit/posix/src/canceleval.c b/cpukit/posix/src/canceleval.c new file mode 100644 index 0000000000..f2e6d9c4c8 --- /dev/null +++ b/cpukit/posix/src/canceleval.c @@ -0,0 +1,38 @@ +/* + * COPYRIGHT (c) 1989-2009. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <rtems/system.h> +#include <rtems/score/thread.h> +#include <rtems/posix/cancel.h> +#include <rtems/posix/pthread.h> + +void _POSIX_Thread_Evaluate_cancellation_and_enable_dispatch( + Thread_Control *the_thread +) +{ + POSIX_API_Control *thread_support; + + thread_support = the_thread->API_Extensions[ THREAD_API_POSIX ]; + + if ( thread_support->cancelability_state == PTHREAD_CANCEL_ENABLE && + thread_support->cancelability_type == PTHREAD_CANCEL_ASYNCHRONOUS && + thread_support->cancelation_requested ) { + _Thread_Unnest_dispatch(); + _POSIX_Thread_Exit( the_thread, PTHREAD_CANCELED ); + } else + _Thread_Enable_dispatch(); + +} diff --git a/cpukit/posix/src/cancelrun.c b/cpukit/posix/src/cancelrun.c new file mode 100644 index 0000000000..8ac96a762d --- /dev/null +++ b/cpukit/posix/src/cancelrun.c @@ -0,0 +1,54 @@ +/* + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/score/chain.h> +#include <rtems/score/isr.h> +#include <rtems/score/thread.h> +#include <rtems/score/wkspace.h> +#include <rtems/posix/cancel.h> +#include <rtems/posix/pthread.h> +#include <rtems/posix/threadsup.h> + +void _POSIX_Threads_cancel_run( + Thread_Control *the_thread +) +{ + POSIX_Cancel_Handler_control *handler; + Chain_Control *handler_stack; + POSIX_API_Control *thread_support; + ISR_Level level; + + thread_support = the_thread->API_Extensions[ THREAD_API_POSIX ]; + + handler_stack = &thread_support->Cancellation_Handlers; + + thread_support->cancelability_state = PTHREAD_CANCEL_DISABLE; + + while ( !_Chain_Is_empty( handler_stack ) ) { + _ISR_Disable( level ); + handler = (POSIX_Cancel_Handler_control *) + _Chain_Tail( handler_stack )->previous; + _Chain_Extract_unprotected( &handler->Node ); + _ISR_Enable( level ); + + (*handler->routine)( handler->arg ); + + _Workspace_Free( handler ); + } +} diff --git a/cpukit/posix/src/cleanuppop.c b/cpukit/posix/src/cleanuppop.c new file mode 100644 index 0000000000..cc327fa33d --- /dev/null +++ b/cpukit/posix/src/cleanuppop.c @@ -0,0 +1,77 @@ +/* + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/score/chain.h> +#include <rtems/score/isr.h> +#include <rtems/score/thread.h> +#include <rtems/score/wkspace.h> +#include <rtems/posix/cancel.h> +#include <rtems/posix/pthread.h> +#include <rtems/posix/threadsup.h> + +/*PAGE + * + * 18.2.3.1 Establishing Cancellation Handlers, P1003.1c/Draft 10, p. 184 + */ + +void pthread_cleanup_pop( + int execute +) +{ + POSIX_Cancel_Handler_control *handler; + POSIX_Cancel_Handler_control tmp_handler; + Chain_Control *handler_stack; + POSIX_API_Control *thread_support; + ISR_Level level; + + thread_support = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ]; + + handler_stack = &thread_support->Cancellation_Handlers; + + /* + * We need interrupts disabled to safely check the chain and pull + * the last element off. But we also need dispatching disabled to + * ensure that we do not get prempted and deleted while we are holding + * memory that needs to be freed. + */ + + _Thread_Disable_dispatch(); + _ISR_Disable( level ); + + if ( _Chain_Is_empty( handler_stack ) ) { + _Thread_Enable_dispatch(); + _ISR_Enable( level ); + return; + } + + handler = (POSIX_Cancel_Handler_control *) + _Chain_Tail( handler_stack )->previous; + _Chain_Extract_unprotected( &handler->Node ); + + _ISR_Enable( level ); + + tmp_handler = *handler; + + _Workspace_Free( handler ); + + _Thread_Enable_dispatch(); + + if ( execute ) + (*tmp_handler.routine)( tmp_handler.arg ); +} diff --git a/cpukit/posix/src/cleanuppush.c b/cpukit/posix/src/cleanuppush.c new file mode 100644 index 0000000000..71079200ef --- /dev/null +++ b/cpukit/posix/src/cleanuppush.c @@ -0,0 +1,64 @@ +/* + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/score/chain.h> +#include <rtems/score/isr.h> +#include <rtems/score/thread.h> +#include <rtems/score/wkspace.h> +#include <rtems/posix/cancel.h> +#include <rtems/posix/pthread.h> +#include <rtems/posix/threadsup.h> + +/*PAGE + * + * 18.2.3.1 Establishing Cancellation Handlers, P1003.1c/Draft 10, p. 184 + */ + +void pthread_cleanup_push( + void (*routine)( void * ), + void *arg +) +{ + POSIX_Cancel_Handler_control *handler; + Chain_Control *handler_stack; + POSIX_API_Control *thread_support; + + /* + * The POSIX standard does not address what to do when the routine + * is NULL. It also does not address what happens when we cannot + * allocate memory or anything else bad happens. + */ + if ( !routine ) + return; + + _Thread_Disable_dispatch(); + handler = _Workspace_Allocate( sizeof( POSIX_Cancel_Handler_control ) ); + + if ( handler ) { + thread_support = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ]; + + handler_stack = &thread_support->Cancellation_Handlers; + + handler->routine = routine; + handler->arg = arg; + + _Chain_Append( handler_stack, &handler->Node ); + } + _Thread_Enable_dispatch(); +} diff --git a/cpukit/posix/src/clockgetcpuclockid.c b/cpukit/posix/src/clockgetcpuclockid.c new file mode 100644 index 0000000000..b4472f8a10 --- /dev/null +++ b/cpukit/posix/src/clockgetcpuclockid.c @@ -0,0 +1,38 @@ +/* + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <time.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/score/isr.h> +#include <rtems/score/thread.h> +#include <rtems/score/tod.h> + +#include <rtems/seterr.h> +#include <rtems/posix/time.h> + +/*PAGE + * + * 20.1.3 Accessing a Process CPU-time CLock, P1003.4b/D8, p. 55 + */ + +int clock_getcpuclockid( + pid_t pid, + clockid_t *clock_id +) +{ + rtems_set_errno_and_return_minus_one( ENOSYS ); +} diff --git a/cpukit/posix/src/clockgetenableattr.c b/cpukit/posix/src/clockgetenableattr.c new file mode 100644 index 0000000000..95efe0de3b --- /dev/null +++ b/cpukit/posix/src/clockgetenableattr.c @@ -0,0 +1,38 @@ +/* + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <time.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/score/isr.h> +#include <rtems/score/thread.h> +#include <rtems/score/tod.h> + +#include <rtems/seterr.h> +#include <rtems/posix/time.h> + +/*PAGE + * + * 20.1.5 CPU-time Clock Attribute Access, P1003.4b/D8, p. 58 + */ + +int clock_getenable_attr( + clockid_t clock_id, + int *attr +) +{ + rtems_set_errno_and_return_minus_one( ENOSYS ); +} diff --git a/cpukit/posix/src/clockgetres.c b/cpukit/posix/src/clockgetres.c new file mode 100644 index 0000000000..7507bee614 --- /dev/null +++ b/cpukit/posix/src/clockgetres.c @@ -0,0 +1,65 @@ +/* + * $Id$ + */ + +/* + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <time.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/config.h> +#include <rtems/score/isr.h> +#include <rtems/score/thread.h> +#include <rtems/score/tod.h> + +#include <rtems/seterr.h> + +/*PAGE + * + * 14.2.1 Clocks, P1003.1b-1993, p. 263 + */ + +int clock_getres( + clockid_t clock_id, + struct timespec *res +) +{ + if ( !res ) + rtems_set_errno_and_return_minus_one( EINVAL ); + + switch ( clock_id ) { + + /* + * All time in rtems is based on the same clock tick. + */ + + case CLOCK_REALTIME: + case CLOCK_PROCESS_CPUTIME: + case CLOCK_THREAD_CPUTIME: + if ( res ) { + res->tv_sec = rtems_configuration_get_microseconds_per_tick() / + TOD_MICROSECONDS_PER_SECOND; + res->tv_nsec = rtems_configuration_get_nanoseconds_per_tick(); + } + break; + + default: + rtems_set_errno_and_return_minus_one( EINVAL ); + + } + return 0; +} diff --git a/cpukit/posix/src/clockgettime.c b/cpukit/posix/src/clockgettime.c new file mode 100644 index 0000000000..852ac8e039 --- /dev/null +++ b/cpukit/posix/src/clockgettime.c @@ -0,0 +1,65 @@ +/* + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <time.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/score/isr.h> +#include <rtems/score/thread.h> +#include <rtems/score/tod.h> + +#include <rtems/seterr.h> + +/*PAGE + * + * 14.2.1 Clocks, P1003.1b-1993, p. 263 + */ + +int clock_gettime( + clockid_t clock_id, + struct timespec *tp +) +{ + if ( !tp ) + rtems_set_errno_and_return_minus_one( EINVAL ); + + if ( clock_id == CLOCK_REALTIME ) { + _TOD_Get(tp); + return 0; + } +#ifdef CLOCK_MONOTONIC + if ( clock_id == CLOCK_MONOTONIC ) { + _TOD_Get_uptime_as_timespec( tp ); + return 0; + } +#endif + +#ifdef _POSIX_CPUTIME + if ( clock_id == CLOCK_PROCESS_CPUTIME ) { + _TOD_Get_uptime_as_timespec( tp ); + return 0; + } +#endif + +#ifdef _POSIX_THREAD_CPUTIME + if ( clock_id == CLOCK_THREAD_CPUTIME ) + rtems_set_errno_and_return_minus_one( ENOSYS ); +#endif + + rtems_set_errno_and_return_minus_one( EINVAL ); + + return 0; +} diff --git a/cpukit/posix/src/clocksetenableattr.c b/cpukit/posix/src/clocksetenableattr.c new file mode 100644 index 0000000000..f11f8d14e8 --- /dev/null +++ b/cpukit/posix/src/clocksetenableattr.c @@ -0,0 +1,38 @@ +/* + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <time.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/score/isr.h> +#include <rtems/score/thread.h> +#include <rtems/score/tod.h> + +#include <rtems/seterr.h> +#include <rtems/posix/time.h> + +/*PAGE + * + * 20.1.5 CPU-time Clock Attribute Access, P1003.4b/D8, p. 58 + */ + +int clock_setenable_attr( + clockid_t clock_id, + int attr +) +{ + rtems_set_errno_and_return_minus_one( ENOSYS ); +} diff --git a/cpukit/posix/src/clocksettime.c b/cpukit/posix/src/clocksettime.c new file mode 100644 index 0000000000..aa3743d9f9 --- /dev/null +++ b/cpukit/posix/src/clocksettime.c @@ -0,0 +1,59 @@ +/* + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <time.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/score/isr.h> +#include <rtems/score/thread.h> +#include <rtems/score/tod.h> + +#include <rtems/seterr.h> + +/*PAGE + * + * 14.2.1 Clocks, P1003.1b-1993, p. 263 + */ + +int clock_settime( + clockid_t clock_id, + const struct timespec *tp +) +{ + if ( !tp ) + rtems_set_errno_and_return_minus_one( EINVAL ); + + if ( clock_id == CLOCK_REALTIME ) { + if ( tp->tv_sec < TOD_SECONDS_1970_THROUGH_1988 ) + rtems_set_errno_and_return_minus_one( EINVAL ); + + _Thread_Disable_dispatch(); + _TOD_Set( tp ); + _Thread_Enable_dispatch(); + } +#ifdef _POSIX_CPUTIME + else if ( clock_id == CLOCK_PROCESS_CPUTIME ) + rtems_set_errno_and_return_minus_one( ENOSYS ); +#endif +#ifdef _POSIX_THREAD_CPUTIME + else if ( clock_id == CLOCK_THREAD_CPUTIME ) + rtems_set_errno_and_return_minus_one( ENOSYS ); +#endif + else + rtems_set_errno_and_return_minus_one( EINVAL ); + + return 0; +} diff --git a/cpukit/posix/src/cond.c b/cpukit/posix/src/cond.c new file mode 100644 index 0000000000..954fb34b78 --- /dev/null +++ b/cpukit/posix/src/cond.c @@ -0,0 +1,59 @@ +/* + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> +#include <limits.h> + +#include <rtems/system.h> +#include <rtems/config.h> +#include <rtems/score/object.h> +#include <rtems/score/states.h> +#include <rtems/score/watchdog.h> +#include <rtems/posix/cond.h> +#include <rtems/posix/time.h> +#include <rtems/posix/mutex.h> + +/*PAGE + * + * _POSIX_Condition_variables_Manager_initialization + * + * This routine initializes all condition variable manager related data + * structures. + * + * Input parameters: NONE + * + * Output parameters: NONE + */ + +void _POSIX_Condition_variables_Manager_initialization(void) +{ + _Objects_Initialize_information( + &_POSIX_Condition_variables_Information, /* object information table */ + OBJECTS_POSIX_API, /* object API */ + OBJECTS_POSIX_CONDITION_VARIABLES, /* object class */ + Configuration_POSIX_API.maximum_condition_variables, + /* maximum objects of this class */ + sizeof( POSIX_Condition_variables_Control ), + /* size of this object's control block */ + true, /* true if names for this object are strings */ + _POSIX_PATH_MAX /* maximum length of each object's name */ +#if defined(RTEMS_MULTIPROCESSING) + , + false, /* true if this is a global object class */ + NULL /* Proxy extraction support callout */ +#endif + ); +} diff --git a/cpukit/posix/src/condattrdestroy.c b/cpukit/posix/src/condattrdestroy.c new file mode 100644 index 0000000000..821f93fba9 --- /dev/null +++ b/cpukit/posix/src/condattrdestroy.c @@ -0,0 +1,42 @@ +/* + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/score/object.h> +#include <rtems/score/states.h> +#include <rtems/score/watchdog.h> +#include <rtems/posix/cond.h> +#include <rtems/posix/time.h> +#include <rtems/posix/mutex.h> + +/*PAGE + * + * 11.4.1 Condition Variable Initialization Attributes, + * P1003.1c/Draft 10, p. 96 + */ + +int pthread_condattr_destroy( + pthread_condattr_t *attr +) +{ + if ( !attr || attr->is_initialized == false ) + return EINVAL; + + attr->is_initialized = false; + return 0; +} diff --git a/cpukit/posix/src/condattrgetpshared.c b/cpukit/posix/src/condattrgetpshared.c new file mode 100644 index 0000000000..0710fcc120 --- /dev/null +++ b/cpukit/posix/src/condattrgetpshared.c @@ -0,0 +1,43 @@ +/* + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/score/object.h> +#include <rtems/score/states.h> +#include <rtems/score/watchdog.h> +#include <rtems/posix/cond.h> +#include <rtems/posix/time.h> +#include <rtems/posix/mutex.h> + +/*PAGE + * + * 11.4.1 Condition Variable Initialization Attributes, + * P1003.1c/Draft 10, p. 96 + */ + +int pthread_condattr_getpshared( + const pthread_condattr_t *attr, + int *pshared +) +{ + if ( !attr ) + return EINVAL; + + *pshared = attr->process_shared; + return 0; +} diff --git a/cpukit/posix/src/condattrinit.c b/cpukit/posix/src/condattrinit.c new file mode 100644 index 0000000000..f06683ad47 --- /dev/null +++ b/cpukit/posix/src/condattrinit.c @@ -0,0 +1,42 @@ +/* + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/score/object.h> +#include <rtems/score/states.h> +#include <rtems/score/watchdog.h> +#include <rtems/posix/cond.h> +#include <rtems/posix/time.h> +#include <rtems/posix/mutex.h> + +/*PAGE + * + * 11.4.1 Condition Variable Initialization Attributes, + * P1003.1c/Draft 10, p. 96 + */ + +int pthread_condattr_init( + pthread_condattr_t *attr +) +{ + if ( !attr ) + return EINVAL; + + *attr = _POSIX_Condition_variables_Default_attributes; + return 0; +} diff --git a/cpukit/posix/src/condattrsetpshared.c b/cpukit/posix/src/condattrsetpshared.c new file mode 100644 index 0000000000..33a4d28a7c --- /dev/null +++ b/cpukit/posix/src/condattrsetpshared.c @@ -0,0 +1,50 @@ +/* + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/score/object.h> +#include <rtems/score/states.h> +#include <rtems/score/watchdog.h> +#include <rtems/posix/cond.h> +#include <rtems/posix/time.h> +#include <rtems/posix/mutex.h> + +/*PAGE + * + * 11.4.1 Condition Variable Initialization Attributes, + * P1003.1c/Draft 10, p. 96 + */ + +int pthread_condattr_setpshared( + pthread_condattr_t *attr, + int pshared +) +{ + if ( !attr ) + return EINVAL; + + switch ( pshared ) { + case PTHREAD_PROCESS_SHARED: + case PTHREAD_PROCESS_PRIVATE: + attr->process_shared = pshared; + return 0; + + default: + return EINVAL; + } +} diff --git a/cpukit/posix/src/condbroadcast.c b/cpukit/posix/src/condbroadcast.c new file mode 100644 index 0000000000..73875f7952 --- /dev/null +++ b/cpukit/posix/src/condbroadcast.c @@ -0,0 +1,37 @@ +/* + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/score/object.h> +#include <rtems/score/states.h> +#include <rtems/score/watchdog.h> +#include <rtems/posix/cond.h> +#include <rtems/posix/time.h> +#include <rtems/posix/mutex.h> + +/*PAGE + * + * 11.4.3 Broadcasting and Signaling a Condition, P1003.1c/Draft 10, p. 101 + */ + +int pthread_cond_broadcast( + pthread_cond_t *cond +) +{ + return _POSIX_Condition_variables_Signal_support( cond, true ); +} diff --git a/cpukit/posix/src/conddefaultattributes.c b/cpukit/posix/src/conddefaultattributes.c new file mode 100644 index 0000000000..7d83bf473c --- /dev/null +++ b/cpukit/posix/src/conddefaultattributes.c @@ -0,0 +1,35 @@ +/* + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/score/object.h> +#include <rtems/score/states.h> +#include <rtems/score/watchdog.h> +#include <rtems/posix/cond.h> +#include <rtems/posix/time.h> +#include <rtems/posix/mutex.h> + +/*PAGE + * + * The default condition variable attributes structure. + */ + +const pthread_condattr_t _POSIX_Condition_variables_Default_attributes = { + true, /* is_initialized */ + PTHREAD_PROCESS_PRIVATE /* process_shared */ +}; diff --git a/cpukit/posix/src/conddestroy.c b/cpukit/posix/src/conddestroy.c new file mode 100644 index 0000000000..d01364f0ef --- /dev/null +++ b/cpukit/posix/src/conddestroy.c @@ -0,0 +1,67 @@ +/* + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/score/object.h> +#include <rtems/score/states.h> +#include <rtems/score/watchdog.h> +#include <rtems/posix/cond.h> +#include <rtems/posix/time.h> +#include <rtems/posix/mutex.h> + +/*PAGE + * + * 11.4.2 Initializing and Destroying a Condition Variable, + * P1003.1c/Draft 10, p. 87 + */ + +int pthread_cond_destroy( + pthread_cond_t *cond +) +{ + POSIX_Condition_variables_Control *the_cond; + Objects_Locations location; + + the_cond = _POSIX_Condition_variables_Get( cond, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + + if ( _Thread_queue_First( &the_cond->Wait_queue ) ) { + _Thread_Enable_dispatch(); + return EBUSY; + } + + _Objects_Close( + &_POSIX_Condition_variables_Information, + &the_cond->Object + ); + + _POSIX_Condition_variables_Free( the_cond ); + _Thread_Enable_dispatch(); + return 0; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: +#endif + case OBJECTS_ERROR: + break; + } + + return EINVAL; +} diff --git a/cpukit/posix/src/condget.c b/cpukit/posix/src/condget.c new file mode 100644 index 0000000000..0305b45e3b --- /dev/null +++ b/cpukit/posix/src/condget.c @@ -0,0 +1,60 @@ +/* + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/score/object.h> +#include <rtems/score/states.h> +#include <rtems/score/watchdog.h> +#include <rtems/posix/cond.h> +#include <rtems/posix/time.h> +#include <rtems/posix/mutex.h> + +POSIX_Condition_variables_Control *_POSIX_Condition_variables_Get ( + pthread_cond_t *cond, + Objects_Locations *location +) +{ + int status; + + if ( !cond ) { + *location = OBJECTS_ERROR; + return (POSIX_Condition_variables_Control *) 0; + } + + if ( *cond == PTHREAD_COND_INITIALIZER ) { + /* + * Do an "auto-create" here. + */ + + status = pthread_cond_init( cond, 0 ); + if ( status ) { + *location = OBJECTS_ERROR; + return (POSIX_Condition_variables_Control *) 0; + } + } + + /* + * Now call Objects_Get() + */ + return (POSIX_Condition_variables_Control *)_Objects_Get( + &_POSIX_Condition_variables_Information, + (Objects_Id) *cond, + location + ); +} + diff --git a/cpukit/posix/src/condinit.c b/cpukit/posix/src/condinit.c new file mode 100644 index 0000000000..8bdbe2be00 --- /dev/null +++ b/cpukit/posix/src/condinit.c @@ -0,0 +1,84 @@ +/* + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/score/object.h> +#include <rtems/score/states.h> +#include <rtems/score/watchdog.h> +#include <rtems/posix/cond.h> +#include <rtems/posix/time.h> +#include <rtems/posix/mutex.h> + +/*PAGE + * + * 11.4.2 Initializing and Destroying a Condition Variable, + * P1003.1c/Draft 10, p. 87 + */ + +int pthread_cond_init( + pthread_cond_t *cond, + const pthread_condattr_t *attr +) +{ + POSIX_Condition_variables_Control *the_cond; + const pthread_condattr_t *the_attr; + + if ( attr ) the_attr = attr; + else the_attr = &_POSIX_Condition_variables_Default_attributes; + + /* + * Be careful about attributes when global!!! + */ + if ( the_attr->process_shared == PTHREAD_PROCESS_SHARED ) + return EINVAL; + + if ( !the_attr->is_initialized ) + return EINVAL; + + _Thread_Disable_dispatch(); + + the_cond = _POSIX_Condition_variables_Allocate(); + + if ( !the_cond ) { + _Thread_Enable_dispatch(); + return ENOMEM; + } + + the_cond->process_shared = the_attr->process_shared; + + the_cond->Mutex = POSIX_CONDITION_VARIABLES_NO_MUTEX; + + _Thread_queue_Initialize( + &the_cond->Wait_queue, + THREAD_QUEUE_DISCIPLINE_FIFO, + STATES_WAITING_FOR_CONDITION_VARIABLE | STATES_INTERRUPTIBLE_BY_SIGNAL, + ETIMEDOUT + ); + + _Objects_Open_u32( + &_POSIX_Condition_variables_Information, + &the_cond->Object, + 0 + ); + + *cond = the_cond->Object.id; + + _Thread_Enable_dispatch(); + + return 0; +} diff --git a/cpukit/posix/src/condsignal.c b/cpukit/posix/src/condsignal.c new file mode 100644 index 0000000000..fd607fd641 --- /dev/null +++ b/cpukit/posix/src/condsignal.c @@ -0,0 +1,37 @@ +/* + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/score/object.h> +#include <rtems/score/states.h> +#include <rtems/score/watchdog.h> +#include <rtems/posix/cond.h> +#include <rtems/posix/time.h> +#include <rtems/posix/mutex.h> + +/*PAGE + * + * 11.4.3 Broadcasting and Signaling a Condition, P1003.1c/Draft 10, p. 101 + */ + +int pthread_cond_signal( + pthread_cond_t *cond +) +{ + return _POSIX_Condition_variables_Signal_support( cond, false ); +} diff --git a/cpukit/posix/src/condsignalsupp.c b/cpukit/posix/src/condsignalsupp.c new file mode 100644 index 0000000000..47e23b5b8e --- /dev/null +++ b/cpukit/posix/src/condsignalsupp.c @@ -0,0 +1,66 @@ +/* + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/score/object.h> +#include <rtems/score/states.h> +#include <rtems/score/watchdog.h> +#include <rtems/posix/cond.h> +#include <rtems/posix/time.h> +#include <rtems/posix/mutex.h> + +/*PAGE + * + * _POSIX_Condition_variables_Signal_support + * + * A support routine which implements guts of the broadcast and single task + * wake up version of the "signal" operation. + */ + +int _POSIX_Condition_variables_Signal_support( + pthread_cond_t *cond, + bool is_broadcast +) +{ + register POSIX_Condition_variables_Control *the_cond; + Objects_Locations location; + Thread_Control *the_thread; + + the_cond = _POSIX_Condition_variables_Get( cond, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + do { + the_thread = _Thread_queue_Dequeue( &the_cond->Wait_queue ); + if ( !the_thread ) + the_cond->Mutex = POSIX_CONDITION_VARIABLES_NO_MUTEX; + } while ( is_broadcast && the_thread ); + + _Thread_Enable_dispatch(); + + return 0; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: +#endif + case OBJECTS_ERROR: + break; + } + + return EINVAL; +} diff --git a/cpukit/posix/src/condtimedwait.c b/cpukit/posix/src/condtimedwait.c new file mode 100644 index 0000000000..4134a73f8a --- /dev/null +++ b/cpukit/posix/src/condtimedwait.c @@ -0,0 +1,70 @@ +/* + * $Id$ + */ + +/* + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/score/object.h> +#include <rtems/score/states.h> +#include <rtems/score/watchdog.h> +#include <rtems/posix/cond.h> +#include <rtems/posix/time.h> +#include <rtems/posix/mutex.h> + +/*PAGE + * + * 11.4.4 Waiting on a Condition, P1003.1c/Draft 10, p. 105 + */ + +int pthread_cond_timedwait( + pthread_cond_t *cond, + pthread_mutex_t *mutex, + const struct timespec *abstime +) +{ + Watchdog_Interval ticks; + bool already_timedout; + POSIX_Absolute_timeout_conversion_results_t status; + + /* + * POSIX requires that blocking calls with timeouts that take + * an absolute timeout must ignore issues with the absolute + * time provided if the operation would otherwise succeed. + * So we check the abstime provided, and hold on to whether it + * is valid or not. If it isn't correct and in the future, + * then we do a polling operation and convert the UNSATISFIED + * status into the appropriate error. + */ + already_timedout = false; + status = _POSIX_Absolute_timeout_to_ticks(abstime, &ticks); + if ( status == POSIX_ABSOLUTE_TIMEOUT_INVALID ) + return EINVAL; + + if ( status == POSIX_ABSOLUTE_TIMEOUT_IS_IN_PAST || + status == POSIX_ABSOLUTE_TIMEOUT_IS_NOW ) + already_timedout = true; + + return _POSIX_Condition_variables_Wait_support( + cond, + mutex, + ticks, + already_timedout + ); +} diff --git a/cpukit/posix/src/condwait.c b/cpukit/posix/src/condwait.c new file mode 100644 index 0000000000..2d925a3b80 --- /dev/null +++ b/cpukit/posix/src/condwait.c @@ -0,0 +1,43 @@ +/* + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/score/object.h> +#include <rtems/score/states.h> +#include <rtems/score/watchdog.h> +#include <rtems/posix/cond.h> +#include <rtems/posix/time.h> +#include <rtems/posix/mutex.h> + +/*PAGE + * + * 11.4.4 Waiting on a Condition, P1003.1c/Draft 10, p. 105 + */ + +int pthread_cond_wait( + pthread_cond_t *cond, + pthread_mutex_t *mutex +) +{ + return _POSIX_Condition_variables_Wait_support( + cond, + mutex, + THREAD_QUEUE_WAIT_FOREVER, + false + ); +} diff --git a/cpukit/posix/src/condwaitsupp.c b/cpukit/posix/src/condwaitsupp.c new file mode 100644 index 0000000000..745d224d3d --- /dev/null +++ b/cpukit/posix/src/condwaitsupp.c @@ -0,0 +1,122 @@ +/* + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/score/object.h> +#include <rtems/score/states.h> +#include <rtems/score/watchdog.h> +#include <rtems/posix/cond.h> +#include <rtems/posix/time.h> +#include <rtems/posix/mutex.h> + +/*PAGE + * + * _POSIX_Condition_variables_Wait_support + * + * A support routine which implements guts of the blocking, non-blocking, and + * timed wait version of condition variable wait routines. + */ + +int _POSIX_Condition_variables_Wait_support( + pthread_cond_t *cond, + pthread_mutex_t *mutex, + Watchdog_Interval timeout, + bool already_timedout +) +{ + register POSIX_Condition_variables_Control *the_cond; + Objects_Locations location; + int status; + int mutex_status; + + if ( !_POSIX_Mutex_Get( mutex, &location ) ) { + return EINVAL; + } + + _Thread_Unnest_dispatch(); + + the_cond = _POSIX_Condition_variables_Get( cond, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + + if ( the_cond->Mutex && ( the_cond->Mutex != *mutex ) ) { + _Thread_Enable_dispatch(); + return EINVAL; + } + + (void) pthread_mutex_unlock( mutex ); +/* XXX ignore this for now since behavior is undefined + if ( mutex_status ) { + _Thread_Enable_dispatch(); + return EINVAL; + } +*/ + + if ( !already_timedout ) { + the_cond->Mutex = *mutex; + + _Thread_queue_Enter_critical_section( &the_cond->Wait_queue ); + _Thread_Executing->Wait.return_code = 0; + _Thread_Executing->Wait.queue = &the_cond->Wait_queue; + _Thread_Executing->Wait.id = *cond; + + _Thread_queue_Enqueue( &the_cond->Wait_queue, timeout ); + + _Thread_Enable_dispatch(); + + /* + * Switch ourself out because we blocked as a result of the + * _Thread_queue_Enqueue. + */ + + /* + * If the thread is interrupted, while in the thread queue, by + * a POSIX signal, then pthread_cond_wait returns spuriously, + * according to the POSIX standard. It means that pthread_cond_wait + * returns a success status, except for the fact that it was not + * woken up a pthread_cond_signal or a pthread_cond_broadcast. + */ + status = _Thread_Executing->Wait.return_code; + if ( status == EINTR ) + status = 0; + + } else { + _Thread_Enable_dispatch(); + status = ETIMEDOUT; + } + + /* + * When we get here the dispatch disable level is 0. + */ + + mutex_status = pthread_mutex_lock( mutex ); + if ( mutex_status ) + return EINVAL; + + return status; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: +#endif + case OBJECTS_ERROR: + break; + } + + return EINVAL; +} diff --git a/cpukit/posix/src/execl.c b/cpukit/posix/src/execl.c new file mode 100644 index 0000000000..9edaba341d --- /dev/null +++ b/cpukit/posix/src/execl.c @@ -0,0 +1,32 @@ +/* + * execl() - POSIX 1003.1b 3.1.2 + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#ifndef HAVE_EXECL + +#include <errno.h> +#include <rtems/seterr.h> + +int execl( + const char *path, + const char *arg, + ... +) +{ + rtems_set_errno_and_return_minus_one( ENOSYS ); +} + +#endif diff --git a/cpukit/posix/src/execle.c b/cpukit/posix/src/execle.c new file mode 100644 index 0000000000..947a4e104f --- /dev/null +++ b/cpukit/posix/src/execle.c @@ -0,0 +1,32 @@ +/* + * execle() - POSIX 1003.1b 3.1.2 + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#ifndef HAVE_EXECLE + +#include <errno.h> +#include <rtems/seterr.h> + +int execle( + const char *path, + char const *arg, + ... +) +{ + rtems_set_errno_and_return_minus_one( ENOSYS ); +} + +#endif diff --git a/cpukit/posix/src/execlp.c b/cpukit/posix/src/execlp.c new file mode 100644 index 0000000000..fabc6986bb --- /dev/null +++ b/cpukit/posix/src/execlp.c @@ -0,0 +1,32 @@ +/* + * execlp() - POSIX 1003.1b 3.1.2 + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#ifndef HAVE_EXECLP + +#include <errno.h> +#include <rtems/seterr.h> + +int execlp( + const char *file, + const char *arg, + ... +) +{ + rtems_set_errno_and_return_minus_one( ENOSYS ); +} + +#endif diff --git a/cpukit/posix/src/execv.c b/cpukit/posix/src/execv.c new file mode 100644 index 0000000000..46595232ad --- /dev/null +++ b/cpukit/posix/src/execv.c @@ -0,0 +1,31 @@ +/* + * execv() - POSIX 1003.1b 3.1.2 + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#ifndef HAVE_EXECV + +#include <errno.h> +#include <rtems/seterr.h> + +int execv( + const char *file, + char *const argv[] +) +{ + rtems_set_errno_and_return_minus_one( ENOSYS ); +} + +#endif diff --git a/cpukit/posix/src/execve.c b/cpukit/posix/src/execve.c new file mode 100644 index 0000000000..b89009866e --- /dev/null +++ b/cpukit/posix/src/execve.c @@ -0,0 +1,32 @@ +/* + * execve() - POSIX 1003.1b 3.1.2 + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#ifndef HAVE_EXECVE + +#include <errno.h> +#include <rtems/seterr.h> + +int execve( + const char *path, + char *const argv[], + char *const envp[] +) +{ + rtems_set_errno_and_return_minus_one( ENOSYS ); +} + +#endif diff --git a/cpukit/posix/src/execvp.c b/cpukit/posix/src/execvp.c new file mode 100644 index 0000000000..720543fcdf --- /dev/null +++ b/cpukit/posix/src/execvp.c @@ -0,0 +1,31 @@ +/* + * execvp() - POSIX 1003.1b 3.1.2 + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#ifndef HAVE_EXECVP + +#include <errno.h> +#include <rtems/seterr.h> + +int execvp( + const char *path, + char *const argv[] +) +{ + rtems_set_errno_and_return_minus_one( ENOSYS ); +} + +#endif diff --git a/cpukit/posix/src/fork.c b/cpukit/posix/src/fork.c new file mode 100644 index 0000000000..f0023e2978 --- /dev/null +++ b/cpukit/posix/src/fork.c @@ -0,0 +1,25 @@ +/* + * fork() - POSIX 1003.1b 3.1.1 + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <sys/types.h> +#include <errno.h> +#include <rtems/seterr.h> + +int fork( void ) +{ + rtems_set_errno_and_return_minus_one( ENOSYS ); +} diff --git a/cpukit/posix/src/getitimer.c b/cpukit/posix/src/getitimer.c new file mode 100644 index 0000000000..8d1bb97904 --- /dev/null +++ b/cpukit/posix/src/getitimer.c @@ -0,0 +1,39 @@ +/* + * COPYRIGHT (c) 1989-20089 + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <time.h> +#include <sys/time.h> +#include <errno.h> +#include <rtems/seterr.h> + +int getitimer( + int which, + struct itimerval *value +) +{ + if ( !value ) + rtems_set_errno_and_return_minus_one( EFAULT ); + + switch ( which ) { + case ITIMER_REAL: + case ITIMER_VIRTUAL: + case ITIMER_PROF: + rtems_set_errno_and_return_minus_one( ENOSYS ); + default: + break; + } + rtems_set_errno_and_return_minus_one( EINVAL ); +} + diff --git a/cpukit/posix/src/key.c b/cpukit/posix/src/key.c new file mode 100644 index 0000000000..a32853cac4 --- /dev/null +++ b/cpukit/posix/src/key.c @@ -0,0 +1,58 @@ +/* + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <errno.h> +#include <limits.h> +#include <pthread.h> +#include <string.h> +#include <limits.h> + +#include <rtems/system.h> +#include <rtems/config.h> +#include <rtems/score/thread.h> +#include <rtems/score/wkspace.h> +#include <rtems/posix/key.h> + +/* + * _POSIX_Key_Manager_initialization + * + * DESCRIPTION: + * + * This routine performs the initialization necessary for this manager. + * + * Input parameters: NONE + * + * Output parameters: NONE + */ + +void _POSIX_Key_Manager_initialization(void) +{ + _Objects_Initialize_information( + &_POSIX_Keys_Information, /* object information table */ + OBJECTS_POSIX_API, /* object API */ + OBJECTS_POSIX_KEYS, /* object class */ + Configuration_POSIX_API.maximum_keys, + /* maximum objects of this class */ + sizeof( POSIX_Keys_Control ), + /* size of this object's control block */ + true, /* true if names for this object are strings */ + _POSIX_PATH_MAX /* maximum length of each object's name */ +#if defined(RTEMS_MULTIPROCESSING) + , + false, /* true if this is a global object class */ + NULL /* Proxy extraction support callout */ +#endif + ); +} diff --git a/cpukit/posix/src/keycreate.c b/cpukit/posix/src/keycreate.c new file mode 100644 index 0000000000..1fc87641e5 --- /dev/null +++ b/cpukit/posix/src/keycreate.c @@ -0,0 +1,99 @@ +/* + * COPYRIGHT (c) 1989-2010. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <errno.h> +#include <limits.h> +#include <pthread.h> +#include <string.h> + +#include <rtems/system.h> +#include <rtems/score/thread.h> +#include <rtems/score/wkspace.h> +#include <rtems/posix/key.h> + +/* + * 17.1.1 Thread-Specific Data Key Create, P1003.1c/Draft 10, p. 163 + */ + +int pthread_key_create( + pthread_key_t *key, + void (*destructor)( void * ) +) +{ + POSIX_Keys_Control *the_key; + void *table; + uint32_t the_api; + uint32_t bytes_to_allocate; + + + _Thread_Disable_dispatch(); + + the_key = _POSIX_Keys_Allocate(); + + if ( !the_key ) { + _Thread_Enable_dispatch(); + return EAGAIN; + } + + the_key->destructor = destructor; + + /* + * This is a bit more complex than one might initially expect because + * APIs are optional. + * + * NOTE: Currently RTEMS Classic API tasks are always enabled. + */ + for ( the_api = 1; the_api <= OBJECTS_APIS_LAST; the_api++ ) { + the_key->Values[ the_api ] = NULL; + + #if defined(RTEMS_DEBUG) + /* + * Since the removal of ITRON, this cannot occur. + */ + if ( !_Objects_Information_table[ the_api ] ) + continue; + + /* + * Currently all managers are installed if the API is installed. + * This would be a horrible implementation error. + */ + if (_Objects_Information_table[ the_api ][ 1 ] == NULL ) + _Internal_error_Occurred( + INTERNAL_ERROR_CORE, + true, + INTERNAL_ERROR_IMPLEMENTATION_KEY_CREATE_INCONSISTENCY + ); + #endif + + bytes_to_allocate = sizeof( void * ) * + (_Objects_Information_table[ the_api ][ 1 ]->maximum + 1); + table = _Workspace_Allocate( bytes_to_allocate ); + if ( !table ) { + _POSIX_Keys_Free_memory( the_key ); + + _POSIX_Keys_Free( the_key ); + _Thread_Enable_dispatch(); + return ENOMEM; + } + + the_key->Values[ the_api ] = table; + memset( table, '\0', bytes_to_allocate ); + } + + _Objects_Open_u32( &_POSIX_Keys_Information, &the_key->Object, 0 ); + *key = the_key->Object.id; + _Thread_Enable_dispatch(); + return 0; +} diff --git a/cpukit/posix/src/keydelete.c b/cpukit/posix/src/keydelete.c new file mode 100644 index 0000000000..99b6e7eedd --- /dev/null +++ b/cpukit/posix/src/keydelete.c @@ -0,0 +1,60 @@ +/* + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <errno.h> +#include <limits.h> +#include <pthread.h> +#include <string.h> + +#include <rtems/system.h> +#include <rtems/score/thread.h> +#include <rtems/score/wkspace.h> +#include <rtems/posix/key.h> + +/* + * 17.1.3 Thread-Specific Data Key Deletion, P1003.1c/Draft 10, p. 167 + */ +int pthread_key_delete( + pthread_key_t key +) +{ + POSIX_Keys_Control *the_key; + Objects_Locations location; + + the_key = _POSIX_Keys_Get( key, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + _Objects_Close( &_POSIX_Keys_Information, &the_key->Object ); + + _POSIX_Keys_Free_memory( the_key ); + + /* + * NOTE: The destructor is not called and it is the responsibility + * of the application to free the memory. + */ + _POSIX_Keys_Free( the_key ); + _Thread_Enable_dispatch(); + return 0; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: /* should never happen */ +#endif + case OBJECTS_ERROR: + break; + } + + return EINVAL; +} diff --git a/cpukit/posix/src/keyfreememory.c b/cpukit/posix/src/keyfreememory.c new file mode 100644 index 0000000000..b6449ffa21 --- /dev/null +++ b/cpukit/posix/src/keyfreememory.c @@ -0,0 +1,29 @@ +/* + * COPYRIGHT (c) 1989-2010. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/score/thread.h> +#include <rtems/score/wkspace.h> +#include <rtems/posix/key.h> + +void _POSIX_Keys_Free_memory( + POSIX_Keys_Control *the_key +) +{ + uint32_t the_api; + + for ( the_api = 1; the_api <= OBJECTS_APIS_LAST; the_api++ ) + _Workspace_Free( the_key->Values[ the_api ] ); +} diff --git a/cpukit/posix/src/keygetspecific.c b/cpukit/posix/src/keygetspecific.c new file mode 100644 index 0000000000..e0acff1455 --- /dev/null +++ b/cpukit/posix/src/keygetspecific.c @@ -0,0 +1,59 @@ +/* + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <errno.h> +#include <limits.h> +#include <pthread.h> +#include <string.h> + +#include <rtems/system.h> +#include <rtems/score/thread.h> +#include <rtems/score/wkspace.h> +#include <rtems/posix/key.h> + +/*PAGE + * + * 17.1.2 Thread-Specific Data Management, P1003.1c/Draft 10, p. 165 + */ + +void *pthread_getspecific( + pthread_key_t key +) +{ + register POSIX_Keys_Control *the_key; + uint32_t api; + uint32_t index; + Objects_Locations location; + void *key_data; + + the_key = _POSIX_Keys_Get( key, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + api = _Objects_Get_API( _Thread_Executing->Object.id ); + index = _Objects_Get_index( _Thread_Executing->Object.id ); + key_data = (void *) the_key->Values[ api ][ index ]; + _Thread_Enable_dispatch(); + return key_data; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: /* should never happen */ +#endif + case OBJECTS_ERROR: + break; + } + + return NULL; +} diff --git a/cpukit/posix/src/keyrundestructors.c b/cpukit/posix/src/keyrundestructors.c new file mode 100644 index 0000000000..cc8bad94e8 --- /dev/null +++ b/cpukit/posix/src/keyrundestructors.c @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2010 embedded brains GmbH. + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/score/object.h> +#include <rtems/score/thread.h> +#include <rtems/posix/key.h> + +/*PAGE + * + * _POSIX_Keys_Run_destructors + * + * 17.1.1 Thread-Specific Data Key Create, P1003.1c/Draft 10, p. 163 + * + * NOTE: This is the routine executed when a thread exits to + * run through all the keys and do the destructor action. + */ + +void _POSIX_Keys_Run_destructors( + Thread_Control *thread +) +{ + Objects_Maximum thread_index = _Objects_Get_index( thread->Object.id ); + Objects_APIs thread_api = _Objects_Get_API( thread->Object.id ); + bool done = false; + + /* + * The standard allows one to avoid a potential infinite loop and limit the + * number of iterations. An infinite loop may happen if destructors set + * thread specific data. This can be considered dubious. + * + * Reference: 17.1.1.2 P1003.1c/Draft 10, p. 163, line 99. + */ + while ( !done ) { + Objects_Maximum index = 0; + Objects_Maximum max = _POSIX_Keys_Information.maximum; + + done = true; + + for ( index = 1 ; index <= max ; ++index ) { + POSIX_Keys_Control *key = (POSIX_Keys_Control *) + _POSIX_Keys_Information.local_table [ index ]; + + if ( key != NULL && key->destructor != NULL ) { + void *value = key->Values [ thread_api ][ thread_index ]; + + if ( value != NULL ) { + key->Values [ thread_api ][ thread_index ] = NULL; + (*key->destructor)( value ); + done = false; + } + } + } + } +} diff --git a/cpukit/posix/src/keysetspecific.c b/cpukit/posix/src/keysetspecific.c new file mode 100644 index 0000000000..8f85ffbcf9 --- /dev/null +++ b/cpukit/posix/src/keysetspecific.c @@ -0,0 +1,59 @@ +/* + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <errno.h> +#include <limits.h> +#include <pthread.h> +#include <string.h> + +#include <rtems/system.h> +#include <rtems/score/thread.h> +#include <rtems/score/wkspace.h> +#include <rtems/posix/key.h> + +/*PAGE + * + * 17.1.2 Thread-Specific Data Management, P1003.1c/Draft 10, p. 165 + */ + +int pthread_setspecific( + pthread_key_t key, + const void *value +) +{ + register POSIX_Keys_Control *the_key; + uint32_t api; + uint32_t index; + Objects_Locations location; + + the_key = _POSIX_Keys_Get( key, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + api = _Objects_Get_API( _Thread_Executing->Object.id ); + index = _Objects_Get_index( _Thread_Executing->Object.id ); + the_key->Values[ api ][ index ] = (void *) value; + _Thread_Enable_dispatch(); + return 0; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: /* should never happen */ +#endif + case OBJECTS_ERROR: + break; + } + + return EINVAL; +} diff --git a/cpukit/posix/src/kill.c b/cpukit/posix/src/kill.c new file mode 100644 index 0000000000..34ea487806 --- /dev/null +++ b/cpukit/posix/src/kill.c @@ -0,0 +1,32 @@ +/* + * 3.3.2 Send a Signal to a Process, P1003.1b-1993, p. 68 + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/pthread.h> +#include <rtems/posix/psignal.h> + +int kill( + pid_t pid, + int sig +) +{ + return killinfo( pid, sig, NULL ); +} + diff --git a/cpukit/posix/src/kill_r.c b/cpukit/posix/src/kill_r.c new file mode 100644 index 0000000000..2da710f799 --- /dev/null +++ b/cpukit/posix/src/kill_r.c @@ -0,0 +1,37 @@ +/* + * 3.3.2 Send a Signal to a Process, P1003.1b-1993, p. 68 + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/pthread.h> +#include <rtems/posix/psignal.h> + +#if defined(RTEMS_NEWLIB) + +#include <reent.h> + +int _kill_r( + struct _reent *ptr, + pid_t pid, + int sig +) +{ + return killinfo( pid, sig, NULL ); +} +#endif diff --git a/cpukit/posix/src/killinfo.c b/cpukit/posix/src/killinfo.c new file mode 100644 index 0000000000..b1569e791b --- /dev/null +++ b/cpukit/posix/src/killinfo.c @@ -0,0 +1,351 @@ +/* + * kill() support routine + * + * COPYRIGHT (c) 1989-2009. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <signal.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/pthread.h> +#include <rtems/posix/psignal.h> +#include <rtems/seterr.h> +#include <rtems/score/isr.h> + +/* + * If you enable this, then you get printk() feedback on each path + * and the input to the decision that lead to the decision. Hopefully + * this will help in debugging the algorithm that distributes process + * signals to individual threads. + */ + +/* #define DEBUG_SIGNAL_PROCESSING */ +#if defined(DEBUG_SIGNAL_PROCESSING) + #include <rtems/bspIo.h> + #define DEBUG_STEP(_x) printk(_x) +#else + #define DEBUG_STEP(_x) +#endif + +/* + * 3.3.2 Send a Signal to a Process, P1003.1b-1993, p. 68 + * + * NOTE: Behavior of kill() depends on _POSIX_SAVED_IDS. + */ + +#define _POSIX_signals_Is_interested( _api, _mask ) \ + ( ~(_api)->signals_blocked & (_mask) ) + +int killinfo( + pid_t pid, + int sig, + const union sigval *value +) +{ + sigset_t mask; + POSIX_API_Control *api; + uint32_t the_api; + uint32_t index; + uint32_t maximum; + Objects_Information *the_info; + Objects_Control **object_table; + Thread_Control *the_thread; + Thread_Control *interested; + Priority_Control interested_priority; + Chain_Control *the_chain; + Chain_Node *the_node; + siginfo_t siginfo_struct; + siginfo_t *siginfo; + POSIX_signals_Siginfo_node *psiginfo; + + /* + * Only supported for the "calling process" (i.e. this node). + */ + if ( pid != getpid() ) + rtems_set_errno_and_return_minus_one( ESRCH ); + + /* + * Validate the signal passed. + */ + if ( !sig ) + rtems_set_errno_and_return_minus_one( EINVAL ); + + if ( !is_valid_signo(sig) ) + rtems_set_errno_and_return_minus_one( EINVAL ); + + /* + * If the signal is being ignored, then we are out of here. + */ + if ( _POSIX_signals_Vectors[ sig ].sa_handler == SIG_IGN ) + return 0; + + /* + * P1003.1c/Draft 10, p. 33 says that certain signals should always + * be directed to the executing thread such as those caused by hardware + * faults. + */ + if ( (sig == SIGFPE) || (sig == SIGILL) || (sig == SIGSEGV ) ) + return pthread_kill( pthread_self(), sig ); + + mask = signo_to_mask( sig ); + + /* + * Build up a siginfo structure + */ + siginfo = &siginfo_struct; + siginfo->si_signo = sig; + siginfo->si_code = SI_USER; + if ( !value ) { + siginfo->si_value.sival_int = 0; + } else { + siginfo->si_value = *value; + } + + _Thread_Disable_dispatch(); + + /* + * Is the currently executing thread interested? If so then it will + * get it an execute it as soon as the dispatcher executes. + */ + the_thread = _Thread_Executing; + + api = the_thread->API_Extensions[ THREAD_API_POSIX ]; + if ( _POSIX_signals_Is_interested( api, mask ) ) { + goto process_it; + } + + /* + * Is an interested thread waiting for this signal (sigwait())? + * + * There is no requirement on the order of threads pending on a sigwait(). + */ + + /* XXX violation of visibility -- need to define thread queue support */ + + the_chain = &_POSIX_signals_Wait_queue.Queues.Fifo; + + for ( the_node = _Chain_First( the_chain ); + !_Chain_Is_tail( the_chain, the_node ) ; + the_node = the_node->next ) { + + the_thread = (Thread_Control *)the_node; + api = the_thread->API_Extensions[ THREAD_API_POSIX ]; + + #if defined(DEBUG_SIGNAL_PROCESSING) + printk( "Waiting Thread=%p option=0x%08x mask=0x%08x blocked=0x%08x\n", + the_thread, the_thread->Wait.option, mask, api->signals_blocked); + #endif + + /* + * Is this thread is actually blocked waiting for the signal? + */ + if (the_thread->Wait.option & mask) + goto process_it; + + /* + * Is this thread is blocked waiting for another signal but has + * not blocked this one? + */ + if (~api->signals_blocked & mask) + goto process_it; + } + + /* + * Is any other thread interested? The highest priority interested + * thread is selected. In the event of a tie, then the following + * additional criteria is used: + * + * + ready thread over blocked + * + blocked on call interruptible by signal (can return EINTR) + * + blocked on call not interruptible by signal + * + * This looks at every thread in the system regardless of the creating API. + * + * NOTES: + * + * + rtems internal threads do not receive signals. + */ + interested = NULL; + interested_priority = PRIORITY_MAXIMUM + 1; + + for (the_api = OBJECTS_CLASSIC_API; the_api <= OBJECTS_APIS_LAST; the_api++) { + + /* + * This can occur when no one is interested and an API is not configured. + */ + if ( !_Objects_Information_table[ the_api ] ) + continue; + + the_info = _Objects_Information_table[ the_api ][ 1 ]; + + #if defined(RTEMS_DEBUG) + /* + * This cannot happen in the current (as of June 2009) implementation + * of initialization but at some point, the object information + * structure for a particular manager may not be installed. + */ + if ( !the_info ) + continue; + #endif + + maximum = the_info->maximum; + object_table = the_info->local_table; + + for ( index = 1 ; index <= maximum ; index++ ) { + the_thread = (Thread_Control *) object_table[ index ]; + + if ( !the_thread ) + continue; + + #if defined(DEBUG_SIGNAL_PROCESSING) + printk("\n 0x%08x/0x%08x %d/%d 0x%08x 1", + the_thread->Object.id, + ((interested) ? interested->Object.id : 0), + the_thread->current_priority, interested_priority, + the_thread->current_state + ); + #endif + + /* + * If this thread is of lower priority than the interested thread, + * go on to the next thread. + */ + if ( the_thread->current_priority > interested_priority ) + continue; + DEBUG_STEP("2"); + + /* + * If this thread is not interested, then go on to the next thread. + */ + api = the_thread->API_Extensions[ THREAD_API_POSIX ]; + + #if defined(RTEMS_DEBUG) + if ( !api ) + continue; + #endif + + if ( !_POSIX_signals_Is_interested( api, mask ) ) + continue; + DEBUG_STEP("3"); + + /* + * Now we know the thread under consideration is interested. + * If the thread under consideration is of higher priority, then + * it becomes the interested thread. + * + * NOTE: We initialized interested_priority to PRIORITY_MAXIMUM + 1 + * so we never have to worry about deferencing a NULL + * interested thread. + */ + if ( the_thread->current_priority < interested_priority ) { + interested = the_thread; + interested_priority = the_thread->current_priority; + continue; + } + DEBUG_STEP("4"); + + /* + * Now the thread and the interested thread have the same priority. + * We have to sort through the combinations of blocked/not blocked + * and blocking interruptibutable by signal. + * + * If the interested thread is ready, don't think about changing. + */ + + if ( interested && !_States_Is_ready( interested->current_state ) ) { + /* preferred ready over blocked */ + DEBUG_STEP("5"); + if ( _States_Is_ready( the_thread->current_state ) ) { + interested = the_thread; + interested_priority = the_thread->current_priority; + continue; + } + + DEBUG_STEP("6"); + /* prefer blocked/interruptible over blocked/not interruptible */ + if ( !_States_Is_interruptible_by_signal(interested->current_state) ) { + DEBUG_STEP("7"); + if ( _States_Is_interruptible_by_signal(the_thread->current_state) ) { + DEBUG_STEP("8"); + interested = the_thread; + interested_priority = the_thread->current_priority; + continue; + } + } + } + } + } + + if ( interested ) { + the_thread = interested; + goto process_it; + } + + /* + * OK so no threads were interested right now. It will be left on the + * global pending until a thread receives it. The global set of threads + * can change interest in this signal in one of the following ways: + * + * + a thread is created with the signal unblocked, + * + pthread_sigmask() unblocks the signal, + * + sigprocmask() unblocks the signal, OR + * + sigaction() which changes the handler to SIG_IGN. + */ + the_thread = NULL; + goto post_process_signal; + + /* + * We found a thread which was interested, so now we mark that this + * thread needs to do the post context switch extension so it can + * evaluate the signals pending. + */ +process_it: + + /* + * Returns true if the signal was synchronously given to a thread + * blocked waiting for the signal. + */ + if ( _POSIX_signals_Unblock_thread( the_thread, sig, siginfo ) ) { + _Thread_Enable_dispatch(); + return 0; + } + +post_process_signal: + + /* + * We may have woken up a thread but we definitely need to post the + * signal to the process wide information set. + */ + _POSIX_signals_Set_process_signals( mask ); + + if ( _POSIX_signals_Vectors[ sig ].sa_flags == SA_SIGINFO ) { + + psiginfo = (POSIX_signals_Siginfo_node *) + _Chain_Get( &_POSIX_signals_Inactive_siginfo ); + if ( !psiginfo ) { + _Thread_Enable_dispatch(); + rtems_set_errno_and_return_minus_one( EAGAIN ); + } + + psiginfo->Info = *siginfo; + + _Chain_Append( &_POSIX_signals_Siginfo[ sig ], &psiginfo->Node ); + } + + DEBUG_STEP("\n"); + _Thread_Enable_dispatch(); + return 0; +} diff --git a/cpukit/posix/src/lio_listio.c b/cpukit/posix/src/lio_listio.c new file mode 100644 index 0000000000..4444b10302 --- /dev/null +++ b/cpukit/posix/src/lio_listio.c @@ -0,0 +1,32 @@ +/* + * 6.7.4 List Directed I/O, P1003.1b-1993, p. 158 + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <aio.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/seterr.h> + +int lio_listio( + int mode __attribute__((unused)), + struct aiocb * const list[] __attribute__((unused)), + int nent __attribute__((unused)), + struct sigevent *sig __attribute__((unused)) +) +{ + rtems_set_errno_and_return_minus_one( ENOSYS ); +} diff --git a/cpukit/posix/src/mprotect.c b/cpukit/posix/src/mprotect.c new file mode 100644 index 0000000000..d3fa8bf9c9 --- /dev/null +++ b/cpukit/posix/src/mprotect.c @@ -0,0 +1,36 @@ +/* + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <unistd.h> + +/*PAGE + * + * 12.2.3 Change Memory Protection, P1003.1b-1996, p. 277. + * + * This is not a functional version but the SPARC backend for at least + * gcc 2.8.1 plus gnat 3.13p and gcc 3.0.1 require it to be there and + * return 0. + * + * As of gcc 4.2.2, the gcc SPARC backend doesn't appear to have a + * way to call this for RTEMS anymore but it doesn't hurt to leave it. + */ + +int mprotect( + const void *addr __attribute__((unused)), + size_t len __attribute__((unused)), + int prot __attribute__((unused)) ) +{ + return 0; +} diff --git a/cpukit/posix/src/mqueue.c b/cpukit/posix/src/mqueue.c new file mode 100644 index 0000000000..5229bd4d67 --- /dev/null +++ b/cpukit/posix/src/mqueue.c @@ -0,0 +1,87 @@ +/* + * NOTE: The structure of the routines is identical to that of POSIX + * Message_queues to leave the option of having unnamed message + * queues at a future date. They are currently not part of the + * POSIX standard but unnamed message_queues are. This is also + * the reason for the apparently unnecessary tracking of + * the process_shared attribute. [In addition to the fact that + * it would be trivial to add pshared to the mq_attr structure + * and have process private message queues.] + * + * This code ignores the O_RDONLY/O_WRONLY/O_RDWR flag at open + * time. + * + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdarg.h> + +#include <pthread.h> +#include <errno.h> +#include <fcntl.h> +#include <mqueue.h> +#include <limits.h> + +#include <rtems/system.h> +#include <rtems/config.h> +#include <rtems/score/watchdog.h> +#include <rtems/seterr.h> +#include <rtems/posix/mqueue.h> +#include <rtems/posix/time.h> + +/*PAGE + * + * _POSIX_Message_queue_Manager_initialization + * + * This routine initializes all message_queue manager related data structures. + * + * Input parameters: NONE + * + * Output parameters: NONE + */ + +void _POSIX_Message_queue_Manager_initialization(void) +{ + _Objects_Initialize_information( + &_POSIX_Message_queue_Information, /* object information table */ + OBJECTS_POSIX_API, /* object API */ + OBJECTS_POSIX_MESSAGE_QUEUES, /* object class */ + Configuration_POSIX_API.maximum_message_queues, + /* maximum objects of this class */ + sizeof( POSIX_Message_queue_Control ), + /* size of this object's control block */ + true, /* true if names for this object are strings */ + _POSIX_PATH_MAX /* maximum length of each object's name */ +#if defined(RTEMS_MULTIPROCESSING) + , + false, /* true if this is a global object class */ + NULL /* Proxy extraction support callout */ +#endif + ); + _Objects_Initialize_information( + &_POSIX_Message_queue_Information_fds, + OBJECTS_POSIX_API, + OBJECTS_POSIX_MESSAGE_QUEUE_FDS, + Configuration_POSIX_API.maximum_message_queue_descriptors, + sizeof( POSIX_Message_queue_Control_fd ), + /* size of this object's control block */ + true, /* true if names for this object are strings */ + NAME_MAX /* maximum length of each object's name */ +#if defined(RTEMS_MULTIPROCESSING) + , + false, /* true if this is a global object class */ + NULL /* Proxy extraction support callout */ +#endif + ); +} diff --git a/cpukit/posix/src/mqueueclose.c b/cpukit/posix/src/mqueueclose.c new file mode 100644 index 0000000000..35b4dc3ec1 --- /dev/null +++ b/cpukit/posix/src/mqueueclose.c @@ -0,0 +1,85 @@ +/* + * NOTE: The structure of the routines is identical to that of POSIX + * Message_queues to leave the option of having unnamed message + * queues at a future date. They are currently not part of the + * POSIX standard but unnamed message_queues are. This is also + * the reason for the apparently unnecessary tracking of + * the process_shared attribute. [In addition to the fact that + * it would be trivial to add pshared to the mq_attr structure + * and have process private message queues.] + * + * This code ignores the O_RDONLY/O_WRONLY/O_RDWR flag at open + * time. + * + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdarg.h> + +#include <pthread.h> +#include <limits.h> +#include <errno.h> +#include <fcntl.h> +#include <mqueue.h> + +#include <rtems/system.h> +#include <rtems/score/watchdog.h> +#include <rtems/seterr.h> +#include <rtems/posix/mqueue.h> +#include <rtems/posix/time.h> + +/* + * + * 15.2.2 Close a Message Queue, P1003.1b-1993, p. 275 + */ + +int mq_close( + mqd_t mqdes +) +{ + POSIX_Message_queue_Control *the_mq; + POSIX_Message_queue_Control_fd *the_mq_fd; + Objects_Locations location; + + the_mq_fd = _POSIX_Message_queue_Get_fd( mqdes, &location ); + if ( location == OBJECTS_LOCAL ) { + /* OBJECTS_LOCAL: + * + * First update the actual message queue to reflect this descriptor + * being disassociated. This may result in the queue being really + * deleted. + */ + + the_mq = the_mq_fd->Queue; + the_mq->open_count -= 1; + _POSIX_Message_queue_Delete( the_mq ); + + /* + * Now close this file descriptor. + */ + + _Objects_Close( + &_POSIX_Message_queue_Information_fds, &the_mq_fd->Object ); + _POSIX_Message_queue_Free_fd( the_mq_fd ); + + _Thread_Enable_dispatch(); + return 0; + } + + /* + * OBJECTS_REMOTE: + * OBJECTS_ERROR: + */ + rtems_set_errno_and_return_minus_one( EBADF ); +} diff --git a/cpukit/posix/src/mqueuecreatesupp.c b/cpukit/posix/src/mqueuecreatesupp.c new file mode 100644 index 0000000000..90bab33ed7 --- /dev/null +++ b/cpukit/posix/src/mqueuecreatesupp.c @@ -0,0 +1,153 @@ +/* + * NOTE: The structure of the routines is identical to that of POSIX + * Message_queues to leave the option of having unnamed message + * queues at a future date. They are currently not part of the + * POSIX standard but unnamed message_queues are. This is also + * the reason for the apparently unnecessary tracking of + * the process_shared attribute. [In addition to the fact that + * it would be trivial to add pshared to the mq_attr structure + * and have process private message queues.] + * + * This code ignores the O_RDONLY/O_WRONLY/O_RDWR flag at open + * time. + * + * COPYRIGHT (c) 1989-2009. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <string.h> +#include <stdarg.h> +#include <stdlib.h> + +#include <pthread.h> +#include <limits.h> +#include <errno.h> +#include <fcntl.h> +#include <mqueue.h> + +#include <rtems/system.h> +#include <rtems/score/watchdog.h> +#include <rtems/score/wkspace.h> +#include <rtems/seterr.h> +#include <rtems/posix/mqueue.h> +#include <rtems/posix/time.h> + +/* pure ANSI mode does not have this prototype */ +size_t strnlen(const char *, size_t); + +/*PAGE + * + * _POSIX_Message_queue_Create_support + * + * This routine does the actual creation and initialization of + * a poxix message queue. + */ + +int _POSIX_Message_queue_Create_support( + const char *name_arg, + int pshared, + struct mq_attr *attr_ptr, + POSIX_Message_queue_Control **message_queue +) +{ + POSIX_Message_queue_Control *the_mq; + CORE_message_queue_Attributes *the_mq_attr; + struct mq_attr attr; + char *name; + size_t n; + + n = strnlen( name_arg, NAME_MAX ); + /* length of name has already been validated */ + + _Thread_Disable_dispatch(); + + /* + * There is no real basis for the default values. They will work + * but were not compared against any existing implementation for + * compatibility. See README.mqueue for an example program we + * think will print out the defaults. Report anything you find with it. + */ + if ( attr_ptr == NULL ) { + attr.mq_maxmsg = 10; + attr.mq_msgsize = 16; + } else { + if ( attr_ptr->mq_maxmsg <= 0 ){ + _Thread_Enable_dispatch(); + rtems_set_errno_and_return_minus_one( EINVAL ); + } + + if ( attr_ptr->mq_msgsize <= 0 ){ + _Thread_Enable_dispatch(); + rtems_set_errno_and_return_minus_one( EINVAL ); + } + + attr = *attr_ptr; + } + + the_mq = _POSIX_Message_queue_Allocate(); + if ( !the_mq ) { + _Thread_Enable_dispatch(); + rtems_set_errno_and_return_minus_one( ENFILE ); + } + + the_mq->process_shared = pshared; + the_mq->named = true; + the_mq->open_count = 1; + the_mq->linked = true; + + /* + * Make a copy of the user's string for name just in case it was + * dynamically constructed. + */ + name = _Workspace_Allocate(n+1); + if (!name) { + _POSIX_Message_queue_Free( the_mq ); + _Thread_Enable_dispatch(); + rtems_set_errno_and_return_minus_one( ENOMEM ); + } + strncpy( name, name_arg, n+1 ); + + /* + * NOTE: That thread blocking discipline should be based on the + * current scheduling policy. + * + * Joel: Cite POSIX or OpenGroup on above statement so we can determine + * if it is a real requirement. + */ + the_mq_attr = &the_mq->Message_queue.Attributes; + the_mq_attr->discipline = CORE_MESSAGE_QUEUE_DISCIPLINES_FIFO; + + if ( !_CORE_message_queue_Initialize( + &the_mq->Message_queue, + the_mq_attr, + attr.mq_maxmsg, + attr.mq_msgsize + ) ) { + + _POSIX_Message_queue_Free( the_mq ); + _Workspace_Free(name); + _Thread_Enable_dispatch(); + rtems_set_errno_and_return_minus_one( ENOSPC ); + } + + _Objects_Open_string( + &_POSIX_Message_queue_Information, + &the_mq->Object, + name + ); + + *message_queue = the_mq; + + _Thread_Enable_dispatch(); + return 0; +} diff --git a/cpukit/posix/src/mqueuedeletesupp.c b/cpukit/posix/src/mqueuedeletesupp.c new file mode 100644 index 0000000000..4c95b08c95 --- /dev/null +++ b/cpukit/posix/src/mqueuedeletesupp.c @@ -0,0 +1,82 @@ +/* + * NOTE: The structure of the routines is identical to that of POSIX + * Message_queues to leave the option of having unnamed message + * queues at a future date. They are currently not part of the + * POSIX standard but unnamed message_queues are. This is also + * the reason for the apparently unnecessary tracking of + * the process_shared attribute. [In addition to the fact that + * it would be trivial to add pshared to the mq_attr structure + * and have process private message queues.] + * + * This code ignores the O_RDONLY/O_WRONLY/O_RDWR flag at open + * time. + * + * COPYRIGHT (c) 1989-2009. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdarg.h> + +#include <pthread.h> +#include <limits.h> +#include <errno.h> +#include <fcntl.h> +#include <mqueue.h> + +#include <rtems/system.h> +#include <rtems/score/watchdog.h> +#include <rtems/score/wkspace.h> +#include <rtems/seterr.h> +#include <rtems/posix/mqueue.h> +#include <rtems/posix/time.h> +#if defined(RTEMS_DEBUG) + #include <rtems/bspIo.h> +#endif + +/*PAGE + * + * _POSIX_Message_queue_Delete + */ + +void _POSIX_Message_queue_Delete( + POSIX_Message_queue_Control *the_mq +) +{ + if ( !the_mq->linked && !the_mq->open_count ) { + Objects_Control *the_object = &the_mq->Object; + + #if defined(RTEMS_DEBUG) + /* + * the name memory will have been freed by unlink. + */ + if ( the_object->name.name_p ) { + printk( + "POSIX MQ name (%p) not freed by unlink\n", + (void *)the_object->name.name_p + ); + _Workspace_Free( (void *)the_object->name.name_p ); + } + #endif + + _Objects_Close( &_POSIX_Message_queue_Information, the_object ); + + _CORE_message_queue_Close( + &the_mq->Message_queue, + NULL, /* no MP support */ + CORE_MESSAGE_QUEUE_STATUS_WAS_DELETED + ); + + _POSIX_Message_queue_Free( the_mq ); + + } +} diff --git a/cpukit/posix/src/mqueuegetattr.c b/cpukit/posix/src/mqueuegetattr.c new file mode 100644 index 0000000000..16a5c50b5f --- /dev/null +++ b/cpukit/posix/src/mqueuegetattr.c @@ -0,0 +1,88 @@ +/* + * NOTE: The structure of the routines is identical to that of POSIX + * Message_queues to leave the option of having unnamed message + * queues at a future date. They are currently not part of the + * POSIX standard but unnamed message_queues are. This is also + * the reason for the apparently unnecessary tracking of + * the process_shared attribute. [In addition to the fact that + * it would be trivial to add pshared to the mq_attr structure + * and have process private message queues.] + * + * This code ignores the O_RDONLY/O_WRONLY/O_RDWR flag at open + * time. + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdarg.h> + +#include <pthread.h> +#include <limits.h> +#include <errno.h> +#include <fcntl.h> +#include <mqueue.h> + +#include <rtems/system.h> +#include <rtems/score/watchdog.h> +#include <rtems/seterr.h> +#include <rtems/posix/mqueue.h> +#include <rtems/posix/time.h> + +/*PAGE + * + * 15.2.8 Get Message Queue Attributes, P1003.1b-1993, p. 283 + */ + +int mq_getattr( + mqd_t mqdes, + struct mq_attr *mqstat +) +{ + POSIX_Message_queue_Control *the_mq; + POSIX_Message_queue_Control_fd *the_mq_fd; + Objects_Locations location; + CORE_message_queue_Attributes *the_mq_attr; + + if ( !mqstat ) + rtems_set_errno_and_return_minus_one( EINVAL ); + + the_mq_fd = _POSIX_Message_queue_Get_fd( mqdes, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + the_mq = the_mq_fd->Queue; + + /* + * Return the old values. + */ + + the_mq_attr = &the_mq->Message_queue.Attributes; + + mqstat->mq_flags = the_mq_fd->oflag; + mqstat->mq_msgsize = the_mq->Message_queue.maximum_message_size; + mqstat->mq_maxmsg = the_mq->Message_queue.maximum_pending_messages; + mqstat->mq_curmsgs = the_mq->Message_queue.number_of_pending_messages; + + _Thread_Enable_dispatch(); + return 0; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: +#endif + case OBJECTS_ERROR: + break; + } + + rtems_set_errno_and_return_minus_one( EBADF ); +} diff --git a/cpukit/posix/src/mqueuenametoid.c b/cpukit/posix/src/mqueuenametoid.c new file mode 100644 index 0000000000..f52e3383c2 --- /dev/null +++ b/cpukit/posix/src/mqueuenametoid.c @@ -0,0 +1,67 @@ +/* + * COPYRIGHT (c) 1989-2009. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdarg.h> + +#include <pthread.h> +#include <limits.h> +#include <errno.h> +#include <fcntl.h> +#include <mqueue.h> + +#include <rtems/system.h> +#include <rtems/score/watchdog.h> +#include <rtems/seterr.h> +#include <rtems/posix/mqueue.h> +#include <rtems/posix/time.h> + +/* pure ANSI mode does not have this prototype */ +size_t strnlen(const char *, size_t); + +/* + * _POSIX_Message_queue_Name_to_id + * + * Look up the specified name and attempt to locate the id + * for the associated message queue. + */ +int _POSIX_Message_queue_Name_to_id( + const char *name, + Objects_Id *id +) +{ + Objects_Name_or_id_lookup_errors status; + Objects_Id the_id; + + if ( !name ) + return EINVAL; + + if ( !name[0] ) + return EINVAL; + + if ( strnlen( name, NAME_MAX ) >= NAME_MAX ) + return ENAMETOOLONG; + + status = _Objects_Name_to_id_string( + &_POSIX_Message_queue_Information, + name, + &the_id + ); + *id = the_id; + + if ( status == OBJECTS_NAME_OR_ID_LOOKUP_SUCCESSFUL ) + return 0; + + return ENOENT; +} diff --git a/cpukit/posix/src/mqueuenotify.c b/cpukit/posix/src/mqueuenotify.c new file mode 100644 index 0000000000..1b9660ccbf --- /dev/null +++ b/cpukit/posix/src/mqueuenotify.c @@ -0,0 +1,116 @@ +/* + * NOTE: The structure of the routines is identical to that of POSIX + * Message_queues to leave the option of having unnamed message + * queues at a future date. They are currently not part of the + * POSIX standard but unnamed message_queues are. This is also + * the reason for the apparently unnecessary tracking of + * the process_shared attribute. [In addition to the fact that + * it would be trivial to add pshared to the mq_attr structure + * and have process private message queues.] + * + * This code ignores the O_RDONLY/O_WRONLY/O_RDWR flag at open + * time. + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdarg.h> + +#include <pthread.h> +#include <limits.h> +#include <errno.h> +#include <fcntl.h> +#include <mqueue.h> +#include <sys/types.h> +#include <signal.h> + +#include <rtems/system.h> +#include <rtems/score/watchdog.h> +#include <rtems/seterr.h> +#include <rtems/posix/mqueue.h> +#include <rtems/posix/time.h> + +/*PAGE + * + * _POSIX_Message_queue_Notify_handler + * + */ + +void _POSIX_Message_queue_Notify_handler( + void *user_data +) +{ + POSIX_Message_queue_Control *the_mq; + + the_mq = user_data; + + kill( getpid(), the_mq->notification.sigev_signo ); + + _CORE_message_queue_Set_notify( &the_mq->Message_queue, NULL, NULL ); +} + +/*PAGE + * + * 15.2.6 Notify Process that a Message is Available on a Queue, + * P1003.1b-1993, p. 280 + */ + +int mq_notify( + mqd_t mqdes, + const struct sigevent *notification +) +{ + POSIX_Message_queue_Control *the_mq; + POSIX_Message_queue_Control_fd *the_mq_fd; + Objects_Locations location; + + the_mq_fd = _POSIX_Message_queue_Get_fd( mqdes, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + the_mq = the_mq_fd->Queue; + + if ( notification ) { + if ( _CORE_message_queue_Is_notify_enabled( &the_mq->Message_queue ) ) { + _Thread_Enable_dispatch(); + rtems_set_errno_and_return_minus_one( EBUSY ); + } + + _CORE_message_queue_Set_notify( &the_mq->Message_queue, NULL, NULL ); + + the_mq->notification = *notification; + + _CORE_message_queue_Set_notify( + &the_mq->Message_queue, + _POSIX_Message_queue_Notify_handler, + the_mq + ); + } else { + + _CORE_message_queue_Set_notify( &the_mq->Message_queue, NULL, NULL ); + + } + + _Thread_Enable_dispatch(); + return 0; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: +#endif + case OBJECTS_ERROR: + break; + } + + rtems_set_errno_and_return_minus_one( EBADF ); +} diff --git a/cpukit/posix/src/mqueueopen.c b/cpukit/posix/src/mqueueopen.c new file mode 100644 index 0000000000..2b96236fb5 --- /dev/null +++ b/cpukit/posix/src/mqueueopen.c @@ -0,0 +1,155 @@ +/* + * NOTE: The structure of the routines is identical to that of POSIX + * Message_queues to leave the option of having unnamed message + * queues at a future date. They are currently not part of the + * POSIX standard but unnamed message_queues are. This is also + * the reason for the apparently unnecessary tracking of + * the process_shared attribute. [In addition to the fact that + * it would be trivial to add pshared to the mq_attr structure + * and have process private message queues.] + * + * This code ignores the O_RDONLY/O_WRONLY/O_RDWR flag at open + * time. + * + * COPYRIGHT (c) 1989-2009. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdarg.h> + +#include <pthread.h> +#include <limits.h> +#include <errno.h> +#include <fcntl.h> +#include <mqueue.h> + +#include <rtems/system.h> +#include <rtems/score/watchdog.h> +#include <rtems/seterr.h> +#include <rtems/posix/mqueue.h> +#include <rtems/posix/time.h> + +/* + * 15.2.2 Open a Message Queue, P1003.1b-1993, p. 272 + */ +mqd_t mq_open( + const char *name, + int oflag, + ... + /* mode_t mode, */ + /* struct mq_attr attr */ +) +{ + va_list arg; + mode_t mode; + struct mq_attr *attr = NULL; + int status; + Objects_Id the_mq_id; + POSIX_Message_queue_Control *the_mq; + POSIX_Message_queue_Control_fd *the_mq_fd; + Objects_Locations location; + + _Thread_Disable_dispatch(); + + if ( oflag & O_CREAT ) { + va_start(arg, oflag); + mode = (mode_t) va_arg( arg, unsigned int ); + attr = (struct mq_attr *) va_arg( arg, struct mq_attr * ); + va_end(arg); + } + + the_mq_fd = _POSIX_Message_queue_Allocate_fd(); + if ( !the_mq_fd ) { + _Thread_Enable_dispatch(); + rtems_set_errno_and_return_minus_one( ENFILE ); + } + the_mq_fd->oflag = oflag; + + status = _POSIX_Message_queue_Name_to_id( name, &the_mq_id ); + + /* + * If the name to id translation worked, then the message queue exists + * and we can just return a pointer to the id. Otherwise we may + * need to check to see if this is a "message queue does not exist" + * or some other miscellaneous error on the name. + */ + if ( status ) { + /* + * Unless provided a valid name that did not already exist + * and we are willing to create then it is an error. + */ + if ( !( status == ENOENT && (oflag & O_CREAT) ) ) { + _POSIX_Message_queue_Free_fd( the_mq_fd ); + _Thread_Enable_dispatch(); + rtems_set_errno_and_return_minus_one_cast( status, mqd_t ); + } + + } else { /* name -> ID translation succeeded */ + /* + * Check for existence with creation. + */ + if ( (oflag & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL) ) { + _POSIX_Message_queue_Free_fd( the_mq_fd ); + _Thread_Enable_dispatch(); + rtems_set_errno_and_return_minus_one_cast( EEXIST, mqd_t ); + } + + /* + * In this case we need to do an ID->pointer conversion to + * check the mode. + */ + the_mq = _POSIX_Message_queue_Get( the_mq_id, &location ); + the_mq->open_count += 1; + the_mq_fd->Queue = the_mq; + _Objects_Open_string( + &_POSIX_Message_queue_Information_fds, + &the_mq_fd->Object, + NULL + ); + _Thread_Enable_dispatch(); + _Thread_Enable_dispatch(); + return (mqd_t)the_mq_fd->Object.id; + + } + + /* + * At this point, the message queue does not exist and everything has been + * checked. We should go ahead and create a message queue. + */ + status = _POSIX_Message_queue_Create_support( + name, + true, /* shared across processes */ + attr, + &the_mq + ); + + /* + * errno was set by Create_support, so don't set it again. + */ + if ( status == -1 ) { + _POSIX_Message_queue_Free_fd( the_mq_fd ); + _Thread_Enable_dispatch(); + return (mqd_t) -1; + } + + the_mq_fd->Queue = the_mq; + _Objects_Open_string( + &_POSIX_Message_queue_Information_fds, + &the_mq_fd->Object, + NULL + ); + + _Thread_Enable_dispatch(); + + return (mqd_t) the_mq_fd->Object.id; +} diff --git a/cpukit/posix/src/mqueuereceive.c b/cpukit/posix/src/mqueuereceive.c new file mode 100644 index 0000000000..46b46b8359 --- /dev/null +++ b/cpukit/posix/src/mqueuereceive.c @@ -0,0 +1,64 @@ +/* + * NOTE: The structure of the routines is identical to that of POSIX + * Message_queues to leave the option of having unnamed message + * queues at a future date. They are currently not part of the + * POSIX standard but unnamed message_queues are. This is also + * the reason for the apparently unnecessary tracking of + * the process_shared attribute. [In addition to the fact that + * it would be trivial to add pshared to the mq_attr structure + * and have process private message queues.] + * + * This code ignores the O_RDONLY/O_WRONLY/O_RDWR flag at open + * time. + * + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdarg.h> + +#include <pthread.h> +#include <limits.h> +#include <errno.h> +#include <fcntl.h> +#include <mqueue.h> + +#include <rtems/system.h> +#include <rtems/score/watchdog.h> +#include <rtems/seterr.h> +#include <rtems/posix/mqueue.h> +#include <rtems/posix/time.h> + +/*PAGE + * + * 15.2.5 Receive a Message From a Message Queue, P1003.1b-1993, p. 279 + * + * NOTE: P1003.4b/D8, p. 45 adds mq_timedreceive(). + */ + +ssize_t mq_receive( + mqd_t mqdes, + char *msg_ptr, + size_t msg_len, + unsigned int *msg_prio +) +{ + return _POSIX_Message_queue_Receive_support( + mqdes, + msg_ptr, + msg_len, + msg_prio, + true, + THREAD_QUEUE_WAIT_FOREVER + ); +} diff --git a/cpukit/posix/src/mqueuerecvsupp.c b/cpukit/posix/src/mqueuerecvsupp.c new file mode 100644 index 0000000000..9c3fb47371 --- /dev/null +++ b/cpukit/posix/src/mqueuerecvsupp.c @@ -0,0 +1,128 @@ +/* + * NOTE: The structure of the routines is identical to that of POSIX + * Message_queues to leave the option of having unnamed message + * queues at a future date. They are currently not part of the + * POSIX standard but unnamed message_queues are. This is also + * the reason for the apparently unnecessary tracking of + * the process_shared attribute. [In addition to the fact that + * it would be trivial to add pshared to the mq_attr structure + * and have process private message queues.] + * + * This code ignores the O_RDONLY/O_WRONLY/O_RDWR flag at open + * time. + * + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdarg.h> + +#include <pthread.h> +#include <limits.h> +#include <errno.h> +#include <fcntl.h> +#include <mqueue.h> + +#include <rtems/system.h> +#include <rtems/score/watchdog.h> +#include <rtems/seterr.h> +#include <rtems/posix/mqueue.h> +#include <rtems/posix/time.h> + +/* + * _POSIX_Message_queue_Receive_support + * + * NOTE: XXX Document how size, priority, length, and the buffer go + * through the layers. + */ + +ssize_t _POSIX_Message_queue_Receive_support( + mqd_t mqdes, + char *msg_ptr, + size_t msg_len, + unsigned int *msg_prio, + bool wait, + Watchdog_Interval timeout +) +{ + POSIX_Message_queue_Control *the_mq; + POSIX_Message_queue_Control_fd *the_mq_fd; + Objects_Locations location; + size_t length_out; + bool do_wait; + + the_mq_fd = _POSIX_Message_queue_Get_fd( mqdes, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + if ( (the_mq_fd->oflag & O_ACCMODE) == O_WRONLY ) { + _Thread_Enable_dispatch(); + rtems_set_errno_and_return_minus_one( EBADF ); + } + + the_mq = the_mq_fd->Queue; + + if ( msg_len < the_mq->Message_queue.maximum_message_size ) { + _Thread_Enable_dispatch(); + rtems_set_errno_and_return_minus_one( EMSGSIZE ); + } + + /* + * Now if something goes wrong, we return a "length" of -1 + * to indicate an error. + */ + + length_out = -1; + + /* + * A timed receive with a bad time will do a poll regardless. + */ + if ( wait ) + do_wait = (the_mq_fd->oflag & O_NONBLOCK) ? false : true; + else + do_wait = wait; + + /* + * Now perform the actual message receive + */ + _CORE_message_queue_Seize( + &the_mq->Message_queue, + mqdes, + msg_ptr, + &length_out, + do_wait, + timeout + ); + + _Thread_Enable_dispatch(); + *msg_prio = + _POSIX_Message_queue_Priority_from_core(_Thread_Executing->Wait.count); + + if ( !_Thread_Executing->Wait.return_code ) + return length_out; + + rtems_set_errno_and_return_minus_one( + _POSIX_Message_queue_Translate_core_message_queue_return_code( + _Thread_Executing->Wait.return_code + ) + ); + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: +#endif + case OBJECTS_ERROR: + break; + } + + rtems_set_errno_and_return_minus_one( EBADF ); +} diff --git a/cpukit/posix/src/mqueuesend.c b/cpukit/posix/src/mqueuesend.c new file mode 100644 index 0000000000..312b04dac2 --- /dev/null +++ b/cpukit/posix/src/mqueuesend.c @@ -0,0 +1,64 @@ +/* + * NOTE: The structure of the routines is identical to that of POSIX + * Message_queues to leave the option of having unnamed message + * queues at a future date. They are currently not part of the + * POSIX standard but unnamed message_queues are. This is also + * the reason for the apparently unnecessary tracking of + * the process_shared attribute. [In addition to the fact that + * it would be trivial to add pshared to the mq_attr structure + * and have process private message queues.] + * + * This code ignores the O_RDONLY/O_WRONLY/O_RDWR flag at open + * time. + * + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdarg.h> + +#include <pthread.h> +#include <limits.h> +#include <errno.h> +#include <fcntl.h> +#include <mqueue.h> + +#include <rtems/system.h> +#include <rtems/score/watchdog.h> +#include <rtems/seterr.h> +#include <rtems/posix/mqueue.h> +#include <rtems/posix/time.h> + +/*PAGE + * + * 15.2.4 Send a Message to a Message Queue, P1003.1b-1993, p. 277 + * + * NOTE: P1003.4b/D8, p. 45 adds mq_timedsend(). + */ + +int mq_send( + mqd_t mqdes, + const char *msg_ptr, + size_t msg_len, + unsigned int msg_prio +) +{ + return _POSIX_Message_queue_Send_support( + mqdes, + msg_ptr, + msg_len, + msg_prio, + true, + THREAD_QUEUE_WAIT_FOREVER + ); +} diff --git a/cpukit/posix/src/mqueuesendsupp.c b/cpukit/posix/src/mqueuesendsupp.c new file mode 100644 index 0000000000..13e91756e8 --- /dev/null +++ b/cpukit/posix/src/mqueuesendsupp.c @@ -0,0 +1,133 @@ +/* + * NOTE: The structure of the routines is identical to that of POSIX + * Message_queues to leave the option of having unnamed message + * queues at a future date. They are currently not part of the + * POSIX standard but unnamed message_queues are. This is also + * the reason for the apparently unnecessary tracking of + * the process_shared attribute. [In addition to the fact that + * it would be trivial to add pshared to the mq_attr structure + * and have process private message queues.] + * + * This code ignores the O_RDONLY/O_WRONLY/O_RDWR flag at open + * time. + * + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdarg.h> + +#include <pthread.h> +#include <limits.h> +#include <errno.h> +#include <fcntl.h> +#include <mqueue.h> + +#include <rtems/system.h> +#include <rtems/score/watchdog.h> +#include <rtems/seterr.h> +#include <rtems/posix/mqueue.h> +#include <rtems/posix/time.h> + + +/*PAGE + * + * _POSIX_Message_queue_Send_support + */ + +int _POSIX_Message_queue_Send_support( + mqd_t mqdes, + const char *msg_ptr, + size_t msg_len, + uint32_t msg_prio, + bool wait, + Watchdog_Interval timeout +) +{ + POSIX_Message_queue_Control *the_mq; + POSIX_Message_queue_Control_fd *the_mq_fd; + Objects_Locations location; + CORE_message_queue_Status msg_status; + bool do_wait; + + /* + * Validate the priority. + * XXX - Do not validate msg_prio is not less than 0. + */ + + if ( msg_prio > MQ_PRIO_MAX ) + rtems_set_errno_and_return_minus_one( EINVAL ); + + the_mq_fd = _POSIX_Message_queue_Get_fd( mqdes, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + if ( (the_mq_fd->oflag & O_ACCMODE) == O_RDONLY ) { + _Thread_Enable_dispatch(); + rtems_set_errno_and_return_minus_one( EBADF ); + } + + the_mq = the_mq_fd->Queue; + + /* + * A timed receive with a bad time will do a poll regardless. + */ + if ( wait ) + do_wait = (the_mq_fd->oflag & O_NONBLOCK) ? false : true; + else + do_wait = wait; + + /* + * Now perform the actual message receive + */ + msg_status = _CORE_message_queue_Submit( + &the_mq->Message_queue, + (void *)msg_ptr, + msg_len, + mqdes, /* mqd_t is an object id */ + NULL, + _POSIX_Message_queue_Priority_to_core( msg_prio ), + do_wait, + timeout /* no timeout */ + ); + + _Thread_Enable_dispatch(); + + /* + * If we had to block, then this is where the task returns + * after it wakes up. The returned status is correct for + * non-blocking operations but if we blocked, then we need + * to look at the status in our TCB. + */ + + if ( msg_status == CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED_WAIT ) + msg_status = _Thread_Executing->Wait.return_code; + + if ( !msg_status ) + return msg_status; + + rtems_set_errno_and_return_minus_one( + _POSIX_Message_queue_Translate_core_message_queue_return_code( + msg_status + ) + ); + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: +#endif + case OBJECTS_ERROR: + break; + } + + rtems_set_errno_and_return_minus_one( EBADF ); +} diff --git a/cpukit/posix/src/mqueuesetattr.c b/cpukit/posix/src/mqueuesetattr.c new file mode 100644 index 0000000000..683c3887b2 --- /dev/null +++ b/cpukit/posix/src/mqueuesetattr.c @@ -0,0 +1,90 @@ +/* + * NOTE: The structure of the routines is identical to that of POSIX + * Message_queues to leave the option of having unnamed message + * queues at a future date. They are currently not part of the + * POSIX standard but unnamed message_queues are. This is also + * the reason for the apparently unnecessary tracking of + * the process_shared attribute. [In addition to the fact that + * it would be trivial to add pshared to the mq_attr structure + * and have process private message queues.] + * + * This code ignores the O_RDONLY/O_WRONLY/O_RDWR flag at open + * time. + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdarg.h> + +#include <pthread.h> +#include <limits.h> +#include <errno.h> +#include <fcntl.h> +#include <mqueue.h> + +#include <rtems/system.h> +#include <rtems/score/watchdog.h> +#include <rtems/seterr.h> +#include <rtems/posix/mqueue.h> +#include <rtems/posix/time.h> + +/*PAGE + * + * 15.2.7 Set Message Queue Attributes, P1003.1b-1993, p. 281 + */ + +int mq_setattr( + mqd_t mqdes, + const struct mq_attr *mqstat, + struct mq_attr *omqstat +) +{ + POSIX_Message_queue_Control_fd *the_mq_fd; + CORE_message_queue_Control *the_core_mq; + Objects_Locations location; + + if ( !mqstat ) + rtems_set_errno_and_return_minus_one( EINVAL ); + + the_mq_fd = _POSIX_Message_queue_Get_fd( mqdes, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + + the_core_mq = &the_mq_fd->Queue->Message_queue; + + /* + * Return the old values. + */ + + if ( omqstat ) { + omqstat->mq_flags = the_mq_fd->oflag; + omqstat->mq_msgsize = the_core_mq->maximum_message_size; + omqstat->mq_maxmsg = the_core_mq->maximum_pending_messages; + omqstat->mq_curmsgs = the_core_mq->number_of_pending_messages; + } + + the_mq_fd->oflag = mqstat->mq_flags; + _Thread_Enable_dispatch(); + return 0; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: +#endif + case OBJECTS_ERROR: + break; + } + + rtems_set_errno_and_return_minus_one( EBADF ); +} diff --git a/cpukit/posix/src/mqueuetimedreceive.c b/cpukit/posix/src/mqueuetimedreceive.c new file mode 100644 index 0000000000..678d364cdf --- /dev/null +++ b/cpukit/posix/src/mqueuetimedreceive.c @@ -0,0 +1,88 @@ +/* + * NOTE: The structure of the routines is identical to that of POSIX + * Message_queues to leave the option of having unnamed message + * queues at a future date. They are currently not part of the + * POSIX standard but unnamed message_queues are. This is also + * the reason for the apparently unnecessary tracking of + * the process_shared attribute. [In addition to the fact that + * it would be trivial to add pshared to the mq_attr structure + * and have process private message queues.] + * + * This code ignores the O_RDONLY/O_WRONLY/O_RDWR flag at open + * time. + */ + +/* + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdarg.h> + +#include <pthread.h> +#include <limits.h> +#include <errno.h> +#include <fcntl.h> +#include <mqueue.h> + +#include <rtems/system.h> +#include <rtems/score/watchdog.h> +#include <rtems/seterr.h> +#include <rtems/posix/mqueue.h> +#include <rtems/posix/time.h> + +/*PAGE + * + * 15.2.5 Receive a Message From a Message Queue, P1003.1b-1993, p. 279 + * + * NOTE: P1003.4b/D8, p. 45 adds mq_timedreceive(). + */ + +ssize_t mq_timedreceive( + mqd_t mqdes, + char *msg_ptr, + size_t msg_len, + unsigned int *msg_prio, + const struct timespec *abstime +) +{ + Watchdog_Interval ticks; + bool do_wait = true; + POSIX_Absolute_timeout_conversion_results_t status; + + /* + * POSIX requires that blocking calls with timeouts that take + * an absolute timeout must ignore issues with the absolute + * time provided if the operation would otherwise succeed. + * So we check the abstime provided, and hold on to whether it + * is valid or not. If it isn't correct and in the future, + * then we do a polling operation and convert the UNSATISFIED + * status into the appropriate error. + * + * If the status is POSIX_ABSOLUTE_TIMEOUT_INVALID, + * POSIX_ABSOLUTE_TIMEOUT_IS_IN_PAST, or POSIX_ABSOLUTE_TIMEOUT_IS_NOW, + * then we should not wait. + */ + status = _POSIX_Absolute_timeout_to_ticks( abstime, &ticks ); + if ( status != POSIX_ABSOLUTE_TIMEOUT_IS_IN_FUTURE ) + do_wait = false; + + return _POSIX_Message_queue_Receive_support( + mqdes, + msg_ptr, + msg_len, + msg_prio, + do_wait, + ticks + ); +} diff --git a/cpukit/posix/src/mqueuetimedsend.c b/cpukit/posix/src/mqueuetimedsend.c new file mode 100644 index 0000000000..9048e8f077 --- /dev/null +++ b/cpukit/posix/src/mqueuetimedsend.c @@ -0,0 +1,88 @@ +/* + * NOTE: The structure of the routines is identical to that of POSIX + * Message_queues to leave the option of having unnamed message + * queues at a future date. They are currently not part of the + * POSIX standard but unnamed message_queues are. This is also + * the reason for the apparently unnecessary tracking of + * the process_shared attribute. [In addition to the fact that + * it would be trivial to add pshared to the mq_attr structure + * and have process private message queues.] + * + * This code ignores the O_RDONLY/O_WRONLY/O_RDWR flag at open + * time. + */ + +/* + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdarg.h> + +#include <pthread.h> +#include <limits.h> +#include <errno.h> +#include <fcntl.h> +#include <mqueue.h> + +#include <rtems/system.h> +#include <rtems/score/watchdog.h> +#include <rtems/seterr.h> +#include <rtems/posix/mqueue.h> +#include <rtems/posix/time.h> + +/*PAGE + * + * 15.2.4 Send a Message to a Message Queue, P1003.1b-1993, p. 277 + * + * NOTE: P1003.4b/D8, p. 45 adds mq_timedsend(). + */ + +int mq_timedsend( + mqd_t mqdes, + const char *msg_ptr, + size_t msg_len, + unsigned int msg_prio, + const struct timespec *abstime +) +{ + Watchdog_Interval ticks; + bool do_wait = true; + POSIX_Absolute_timeout_conversion_results_t status; + + /* + * POSIX requires that blocking calls with timeouts that take + * an absolute timeout must ignore issues with the absolute + * time provided if the operation would otherwise succeed. + * So we check the abstime provided, and hold on to whether it + * is valid or not. If it isn't correct and in the future, + * then we do a polling operation and convert the UNSATISFIED + * status into the appropriate error. + * + * If the status is POSIX_ABSOLUTE_TIMEOUT_INVALID, + * POSIX_ABSOLUTE_TIMEOUT_IS_IN_PAST, or POSIX_ABSOLUTE_TIMEOUT_IS_NOW, + * then we should not wait. + */ + status = _POSIX_Absolute_timeout_to_ticks( abstime, &ticks ); + if ( status != POSIX_ABSOLUTE_TIMEOUT_IS_IN_FUTURE ) + do_wait = false; + + return _POSIX_Message_queue_Send_support( + mqdes, + msg_ptr, + msg_len, + msg_prio, + do_wait, + ticks + ); +} diff --git a/cpukit/posix/src/mqueuetranslatereturncode.c b/cpukit/posix/src/mqueuetranslatereturncode.c new file mode 100644 index 0000000000..9fe57a9920 --- /dev/null +++ b/cpukit/posix/src/mqueuetranslatereturncode.c @@ -0,0 +1,62 @@ +/* + * POSIX Message Queue Error Translation + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/score/coremsg.h> + + +/*PAGE + * + * _POSIX_Message_queue_Translate_core_message_queue_return_code + * + * Input parameters: + * the_message_queue_status - message_queue status code to translate + * + * Output parameters: + * status code - translated POSIX status code + * + */ + +static + int _POSIX_Message_queue_Return_codes[CORE_MESSAGE_QUEUE_STATUS_LAST + 1] = { + 0, /* CORE_MESSAGE_QUEUE_STATUS_SUCCESSFUL */ + EMSGSIZE, /* CORE_MESSAGE_QUEUE_STATUS_INVALID_SIZE */ + EAGAIN, /* CORE_MESSAGE_QUEUE_STATUS_TOO_MANY */ + ENOMEM, /* CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED */ + EAGAIN, /* CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED_NOWAIT */ + EBADF, /* CORE_MESSAGE_QUEUE_STATUS_WAS_DELETED */ + ETIMEDOUT, /* CORE_MESSAGE_QUEUE_STATUS_TIMEOUT */ + ENOSYS /* CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED_WAIT */ +}; + + +int _POSIX_Message_queue_Translate_core_message_queue_return_code( + uint32_t the_message_queue_status +) +{ + /* + * Internal consistency check for bad status from SuperCore + */ + #if defined(RTEMS_DEBUG) + if ( the_message_queue_status > CORE_MESSAGE_QUEUE_STATUS_LAST ) + return EINVAL; + #endif + return _POSIX_Message_queue_Return_codes[the_message_queue_status]; +} diff --git a/cpukit/posix/src/mqueueunlink.c b/cpukit/posix/src/mqueueunlink.c new file mode 100644 index 0000000000..67bb26928f --- /dev/null +++ b/cpukit/posix/src/mqueueunlink.c @@ -0,0 +1,75 @@ +/* + * NOTE: The structure of the routines is identical to that of POSIX + * Message_queues to leave the option of having unnamed message + * queues at a future date. They are currently not part of the + * POSIX standard but unnamed message_queues are. This is also + * the reason for the apparently unnecessary tracking of + * the process_shared attribute. [In addition to the fact that + * it would be trivial to add pshared to the mq_attr structure + * and have process private message queues.] + * + * This code ignores the O_RDONLY/O_WRONLY/O_RDWR flag at open + * time. + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdarg.h> + +#include <pthread.h> +#include <limits.h> +#include <errno.h> +#include <fcntl.h> +#include <mqueue.h> + +#include <rtems/system.h> +#include <rtems/score/watchdog.h> +#include <rtems/score/wkspace.h> +#include <rtems/seterr.h> +#include <rtems/posix/mqueue.h> +#include <rtems/posix/time.h> + +/*PAGE + * + * 15.2.2 Remove a Message Queue, P1003.1b-1993, p. 276 + */ + +int mq_unlink( + const char *name +) +{ + int status; + register POSIX_Message_queue_Control *the_mq; + Objects_Id the_mq_id; + + _Thread_Disable_dispatch(); + + status = _POSIX_Message_queue_Name_to_id( name, &the_mq_id ); + if ( status != 0 ) { + _Thread_Enable_dispatch(); + rtems_set_errno_and_return_minus_one( status ); + } + + the_mq = (POSIX_Message_queue_Control *) _Objects_Get_local_object( + &_POSIX_Message_queue_Information, + _Objects_Get_index( the_mq_id ) + ); + + the_mq->linked = false; + _POSIX_Message_queue_Namespace_remove( the_mq ); + _POSIX_Message_queue_Delete( the_mq ); + + _Thread_Enable_dispatch(); + return 0; +} diff --git a/cpukit/posix/src/mutex.c b/cpukit/posix/src/mutex.c new file mode 100644 index 0000000000..6046b219f5 --- /dev/null +++ b/cpukit/posix/src/mutex.c @@ -0,0 +1,79 @@ +/* + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <errno.h> +#include <pthread.h> +#include <limits.h> + +#include <rtems/system.h> +#include <rtems/config.h> +#include <rtems/score/coremutex.h> +#include <rtems/score/watchdog.h> +#if defined(RTEMS_MULTIPROCESSING) +#include <rtems/score/mpci.h> +#endif +#include <rtems/posix/mutex.h> +#include <rtems/posix/priority.h> +#include <rtems/posix/time.h> + +/*PAGE + * + * _POSIX_Mutex_Manager_initialization + * + * This routine initializes all mutex manager related data structures. + * + * Input parameters: + * maximum_mutexes - maximum configured mutexes + * + * Output parameters: NONE + */ + +void _POSIX_Mutex_Manager_initialization(void) +{ + pthread_mutexattr_t *default_attr = &_POSIX_Mutex_Default_attributes; + + /* + * Since the maximum priority is run-time configured, this + * structure cannot be initialized statically. + */ + default_attr->is_initialized = true; + default_attr->process_shared = PTHREAD_PROCESS_PRIVATE; + default_attr->prio_ceiling = POSIX_SCHEDULER_MAXIMUM_PRIORITY; + default_attr->protocol = PTHREAD_PRIO_NONE; + default_attr->recursive = false; + #if defined(_UNIX98_THREAD_MUTEX_ATTRIBUTES) + default_attr->type = PTHREAD_MUTEX_DEFAULT; + #endif + + /* + * Initialize the POSIX mutex object class information structure. + */ + _Objects_Initialize_information( + &_POSIX_Mutex_Information, /* object information table */ + OBJECTS_POSIX_API, /* object API */ + OBJECTS_POSIX_MUTEXES, /* object class */ + Configuration_POSIX_API.maximum_mutexes, + /* maximum objects of this class */ + sizeof( POSIX_Mutex_Control ), + /* size of this object's control block */ + true, /* true if names for this object are strings */ + _POSIX_PATH_MAX /* maximum length of each object's name */ +#if defined(RTEMS_MULTIPROCESSING) + , + false, /* true if this is a global object class */ + NULL /* Proxy extraction support callout */ +#endif + ); +} diff --git a/cpukit/posix/src/mutexattrdestroy.c b/cpukit/posix/src/mutexattrdestroy.c new file mode 100644 index 0000000000..86e8c4597c --- /dev/null +++ b/cpukit/posix/src/mutexattrdestroy.c @@ -0,0 +1,40 @@ +/* + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <errno.h> +#include <pthread.h> + +#include <rtems/system.h> +#include <rtems/score/coremutex.h> +#include <rtems/score/watchdog.h> +#include <rtems/posix/mutex.h> +#include <rtems/posix/priority.h> +#include <rtems/posix/time.h> + +/*PAGE + * + * 11.3.1 Mutex Initialization Attributes, P1003.1c/Draft 10, p. 81 + */ + +int pthread_mutexattr_destroy( + pthread_mutexattr_t *attr +) +{ + if ( !attr || !attr->is_initialized ) + return EINVAL; + + attr->is_initialized = false; + return 0; +} diff --git a/cpukit/posix/src/mutexattrgetprioceiling.c b/cpukit/posix/src/mutexattrgetprioceiling.c new file mode 100644 index 0000000000..65944687aa --- /dev/null +++ b/cpukit/posix/src/mutexattrgetprioceiling.c @@ -0,0 +1,41 @@ +/* + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <errno.h> +#include <pthread.h> + +#include <rtems/system.h> +#include <rtems/score/coremutex.h> +#include <rtems/score/watchdog.h> +#include <rtems/posix/mutex.h> +#include <rtems/posix/priority.h> +#include <rtems/posix/time.h> + +/*PAGE + * + * 13.6.1 Mutex Initialization Scheduling Attributes, P1003.1c/Draft 10, p. 128 + */ + +int pthread_mutexattr_getprioceiling( + const pthread_mutexattr_t *attr, + int *prioceiling +) +{ + if ( !attr || !attr->is_initialized || !prioceiling ) + return EINVAL; + + *prioceiling = attr->prio_ceiling; + return 0; +} diff --git a/cpukit/posix/src/mutexattrgetprotocol.c b/cpukit/posix/src/mutexattrgetprotocol.c new file mode 100644 index 0000000000..6cd09979c8 --- /dev/null +++ b/cpukit/posix/src/mutexattrgetprotocol.c @@ -0,0 +1,41 @@ +/* + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <errno.h> +#include <pthread.h> + +#include <rtems/system.h> +#include <rtems/score/coremutex.h> +#include <rtems/score/watchdog.h> +#include <rtems/posix/mutex.h> +#include <rtems/posix/priority.h> +#include <rtems/posix/time.h> + +/*PAGE + * + * 13.6.1 Mutex Initialization Scheduling Attributes, P1003.1c/Draft 10, p. 128 + */ + +int pthread_mutexattr_getprotocol( + const pthread_mutexattr_t *attr, + int *protocol +) +{ + if ( !attr || !attr->is_initialized || !protocol ) + return EINVAL; + + *protocol = attr->protocol; + return 0; +} diff --git a/cpukit/posix/src/mutexattrgetpshared.c b/cpukit/posix/src/mutexattrgetpshared.c new file mode 100644 index 0000000000..162de9fe4d --- /dev/null +++ b/cpukit/posix/src/mutexattrgetpshared.c @@ -0,0 +1,41 @@ +/* + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <errno.h> +#include <pthread.h> + +#include <rtems/system.h> +#include <rtems/score/coremutex.h> +#include <rtems/score/watchdog.h> +#include <rtems/posix/mutex.h> +#include <rtems/posix/priority.h> +#include <rtems/posix/time.h> + +/*PAGE + * + * 11.3.1 Mutex Initialization Attributes, P1003.1c/Draft 10, p. 81 + */ + +int pthread_mutexattr_getpshared( + const pthread_mutexattr_t *attr, + int *pshared +) +{ + if ( !attr || !attr->is_initialized || !pshared ) + return EINVAL; + + *pshared = attr->process_shared; + return 0; +} diff --git a/cpukit/posix/src/mutexattrgettype.c b/cpukit/posix/src/mutexattrgettype.c new file mode 100644 index 0000000000..59b69de0d9 --- /dev/null +++ b/cpukit/posix/src/mutexattrgettype.c @@ -0,0 +1,45 @@ +/* + * COPYRIGHT (c) 1989-2009. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <errno.h> +#include <pthread.h> + +#include <rtems/system.h> +#include <rtems/score/coremutex.h> +#include <rtems/score/watchdog.h> +#include <rtems/posix/mutex.h> +#include <rtems/posix/priority.h> +#include <rtems/posix/time.h> + +#if defined(_UNIX98_THREAD_MUTEX_ATTRIBUTES) +int pthread_mutexattr_gettype( + const pthread_mutexattr_t *attr, + int *type +) +{ + if ( !attr ) + return EINVAL; + + if ( !attr->is_initialized ) + return EINVAL; + + if ( !type ) + return EINVAL; + + *type = attr->type; + return 0; +} +#endif + diff --git a/cpukit/posix/src/mutexattrinit.c b/cpukit/posix/src/mutexattrinit.c new file mode 100644 index 0000000000..9f6988fab2 --- /dev/null +++ b/cpukit/posix/src/mutexattrinit.c @@ -0,0 +1,40 @@ +/* + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <errno.h> +#include <pthread.h> + +#include <rtems/system.h> +#include <rtems/score/coremutex.h> +#include <rtems/score/watchdog.h> +#include <rtems/posix/mutex.h> +#include <rtems/posix/priority.h> +#include <rtems/posix/time.h> + +/*PAGE + * + * 11.3.1 Mutex Initialization Attributes, P1003.1c/Draft 10, p. 81 + */ + +int pthread_mutexattr_init( + pthread_mutexattr_t *attr +) +{ + if ( !attr ) + return EINVAL; + + *attr = _POSIX_Mutex_Default_attributes; + return 0; +} diff --git a/cpukit/posix/src/mutexattrsetprioceiling.c b/cpukit/posix/src/mutexattrsetprioceiling.c new file mode 100644 index 0000000000..aee51cc6e5 --- /dev/null +++ b/cpukit/posix/src/mutexattrsetprioceiling.c @@ -0,0 +1,44 @@ +/* + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <errno.h> +#include <pthread.h> + +#include <rtems/system.h> +#include <rtems/score/coremutex.h> +#include <rtems/score/watchdog.h> +#include <rtems/posix/mutex.h> +#include <rtems/posix/priority.h> +#include <rtems/posix/time.h> + +/*PAGE + * + * 13.6.1 Mutex Initialization Scheduling Attributes, P1003.1c/Draft 10, p. 128 + */ + +int pthread_mutexattr_setprioceiling( + pthread_mutexattr_t *attr, + int prioceiling +) +{ + if ( !attr || !attr->is_initialized ) + return EINVAL; + + if ( !_POSIX_Priority_Is_valid( prioceiling ) ) + return EINVAL; + + attr->prio_ceiling = prioceiling; + return 0; +} diff --git a/cpukit/posix/src/mutexattrsetprotocol.c b/cpukit/posix/src/mutexattrsetprotocol.c new file mode 100644 index 0000000000..54d0c4ab8d --- /dev/null +++ b/cpukit/posix/src/mutexattrsetprotocol.c @@ -0,0 +1,49 @@ +/* + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <errno.h> +#include <pthread.h> + +#include <rtems/system.h> +#include <rtems/score/coremutex.h> +#include <rtems/score/watchdog.h> +#include <rtems/posix/mutex.h> +#include <rtems/posix/priority.h> +#include <rtems/posix/time.h> + +/*PAGE + * + * 13.6.1 Mutex Initialization Scheduling Attributes, P1003.1c/Draft 10, p. 128 + */ + +int pthread_mutexattr_setprotocol( + pthread_mutexattr_t *attr, + int protocol +) +{ + if ( !attr || !attr->is_initialized ) + return EINVAL; + + switch ( protocol ) { + case PTHREAD_PRIO_NONE: + case PTHREAD_PRIO_INHERIT: + case PTHREAD_PRIO_PROTECT: + attr->protocol = protocol; + return 0; + + default: + return EINVAL; + } +} diff --git a/cpukit/posix/src/mutexattrsetpshared.c b/cpukit/posix/src/mutexattrsetpshared.c new file mode 100644 index 0000000000..58dc5fd9d0 --- /dev/null +++ b/cpukit/posix/src/mutexattrsetpshared.c @@ -0,0 +1,48 @@ +/* + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <errno.h> +#include <pthread.h> + +#include <rtems/system.h> +#include <rtems/score/coremutex.h> +#include <rtems/score/watchdog.h> +#include <rtems/posix/mutex.h> +#include <rtems/posix/priority.h> +#include <rtems/posix/time.h> + +/*PAGE + * + * 11.3.1 Mutex Initialization Attributes, P1003.1c/Draft 10, p. 81 + */ + +int pthread_mutexattr_setpshared( + pthread_mutexattr_t *attr, + int pshared +) +{ + if ( !attr || !attr->is_initialized ) + return EINVAL; + + switch ( pshared ) { + case PTHREAD_PROCESS_SHARED: + case PTHREAD_PROCESS_PRIVATE: + attr->process_shared = pshared; + return 0; + + default: + return EINVAL; + } +} diff --git a/cpukit/posix/src/mutexattrsettype.c b/cpukit/posix/src/mutexattrsettype.c new file mode 100644 index 0000000000..1cfb94d4d9 --- /dev/null +++ b/cpukit/posix/src/mutexattrsettype.c @@ -0,0 +1,47 @@ +/* + * COPYRIGHT (c) 1989-2009. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <errno.h> +#include <pthread.h> + +#include <rtems/system.h> +#include <rtems/score/coremutex.h> +#include <rtems/score/watchdog.h> +#include <rtems/posix/mutex.h> +#include <rtems/posix/priority.h> +#include <rtems/posix/time.h> + +#if defined(_UNIX98_THREAD_MUTEX_ATTRIBUTES) +int pthread_mutexattr_settype( + pthread_mutexattr_t *attr, + int type +) +{ + if ( !attr || !attr->is_initialized ) + return EINVAL; + + switch ( type ) { + case PTHREAD_MUTEX_NORMAL: + case PTHREAD_MUTEX_RECURSIVE: + case PTHREAD_MUTEX_ERRORCHECK: + case PTHREAD_MUTEX_DEFAULT: + attr->type = type; + return 0; + + default: + return EINVAL; + } +} +#endif diff --git a/cpukit/posix/src/mutexdestroy.c b/cpukit/posix/src/mutexdestroy.c new file mode 100644 index 0000000000..f8c01549c7 --- /dev/null +++ b/cpukit/posix/src/mutexdestroy.c @@ -0,0 +1,68 @@ +/* + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <errno.h> +#include <pthread.h> + +#include <rtems/system.h> +#include <rtems/score/coremutex.h> +#include <rtems/score/watchdog.h> +#include <rtems/posix/mutex.h> +#include <rtems/posix/priority.h> +#include <rtems/posix/time.h> + +/*PAGE + * + * 11.3.2 Initializing and Destroying a Mutex, P1003.1c/Draft 10, p. 87 + */ + +int pthread_mutex_destroy( + pthread_mutex_t *mutex +) +{ + register POSIX_Mutex_Control *the_mutex; + Objects_Locations location; + + the_mutex = _POSIX_Mutex_Get( mutex, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + /* + * XXX: There is an error for the mutex being locked + * or being in use by a condition variable. + */ + + if ( _CORE_mutex_Is_locked( &the_mutex->Mutex ) ) { + _Thread_Enable_dispatch(); + return EBUSY; + } + + _Objects_Close( &_POSIX_Mutex_Information, &the_mutex->Object ); + + _CORE_mutex_Flush( &the_mutex->Mutex, NULL, EINVAL ); + + _POSIX_Mutex_Free( the_mutex ); + _Thread_Enable_dispatch(); + return 0; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: +#endif + case OBJECTS_ERROR: + break; + } + + return EINVAL; +} diff --git a/cpukit/posix/src/mutexget.c b/cpukit/posix/src/mutexget.c new file mode 100644 index 0000000000..71e46766ba --- /dev/null +++ b/cpukit/posix/src/mutexget.c @@ -0,0 +1,91 @@ +/* + * Convert POSIX Mutex ID to local object pointer + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <errno.h> +#include <pthread.h> + +#include <rtems/system.h> +#include <rtems/score/coremutex.h> +#if defined(RTEMS_MULTIPROCESSING) +#include <rtems/score/mpci.h> +#endif +#include <rtems/posix/mutex.h> + + +/* + * _POSIX_Mutex_Get_support + * + * NOTE: The support macro makes it possible for both to use exactly + * the same code to check for NULL id pointer and + * PTHREAD_MUTEX_INITIALIZER without adding overhead. + */ + +#define ___POSIX_Mutex_Get_support_error_check( _id, _location ) \ + do { \ + if ( !_id ) { \ + *_location = OBJECTS_ERROR; \ + return (POSIX_Mutex_Control *) 0; \ + } \ + } while (0) + +#define ___POSIX_Mutex_Get_support_auto_initialization( _id, _location ) \ + do { \ + int _status; \ + \ + if ( *_id == PTHREAD_MUTEX_INITIALIZER ) { \ + /* \ + * Do an "auto-create" here. \ + */ \ + \ + _status = pthread_mutex_init( (pthread_mutex_t *)_id, 0 ); \ + if ( _status ) { \ + *_location = OBJECTS_ERROR; \ + return (POSIX_Mutex_Control *) 0; \ + } \ + } \ + } while (0) + +POSIX_Mutex_Control *_POSIX_Mutex_Get ( + pthread_mutex_t *mutex, + Objects_Locations *location +) +{ + ___POSIX_Mutex_Get_support_error_check( mutex, location ); + + ___POSIX_Mutex_Get_support_auto_initialization( mutex, location ); + + return (POSIX_Mutex_Control *) + _Objects_Get( &_POSIX_Mutex_Information, (Objects_Id) *mutex, location ); +} + +POSIX_Mutex_Control *_POSIX_Mutex_Get_interrupt_disable ( + pthread_mutex_t *mutex, + Objects_Locations *location, + ISR_Level *level +) +{ + ___POSIX_Mutex_Get_support_error_check( mutex, location ); + + ___POSIX_Mutex_Get_support_auto_initialization( mutex, location ); + + return (POSIX_Mutex_Control *) _Objects_Get_isr_disable( + &_POSIX_Mutex_Information, + (Objects_Id) *mutex, + location, + level + ); +} diff --git a/cpukit/posix/src/mutexgetprioceiling.c b/cpukit/posix/src/mutexgetprioceiling.c new file mode 100644 index 0000000000..58537d9242 --- /dev/null +++ b/cpukit/posix/src/mutexgetprioceiling.c @@ -0,0 +1,63 @@ +/* + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <errno.h> +#include <pthread.h> + +#include <rtems/system.h> +#include <rtems/score/coremutex.h> +#include <rtems/score/watchdog.h> +#if defined(RTEMS_MULTIPROCESSING) +#include <rtems/score/mpci.h> +#endif +#include <rtems/posix/mutex.h> +#include <rtems/posix/priority.h> +#include <rtems/posix/time.h> + +/*PAGE + * + * 13.6.2 Change the Priority Ceiling of a Mutex, P1003.1c/Draft 10, p. 131 + */ + +int pthread_mutex_getprioceiling( + pthread_mutex_t *mutex, + int *prioceiling +) +{ + register POSIX_Mutex_Control *the_mutex; + Objects_Locations location; + + if ( !prioceiling ) + return EINVAL; + + the_mutex = _POSIX_Mutex_Get( mutex, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + *prioceiling = _POSIX_Priority_From_core( + the_mutex->Mutex.Attributes.priority_ceiling + ); + _Thread_Enable_dispatch(); + return 0; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: +#endif + case OBJECTS_ERROR: + break; + } + + return EINVAL; +} diff --git a/cpukit/posix/src/mutexinit.c b/cpukit/posix/src/mutexinit.c new file mode 100644 index 0000000000..d6102d44a1 --- /dev/null +++ b/cpukit/posix/src/mutexinit.c @@ -0,0 +1,188 @@ +/* + * COPYRIGHT (c) 1989-2009. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <errno.h> +#include <pthread.h> + +#include <rtems/system.h> +#include <rtems/score/coremutex.h> +#include <rtems/score/watchdog.h> +#include <rtems/posix/mutex.h> +#include <rtems/posix/priority.h> +#include <rtems/posix/time.h> + +/*PAGE + * + * 11.3.2 Initializing and Destroying a Mutex, P1003.1c/Draft 10, p. 87 + * + * NOTE: XXX Could be optimized so all the attribute error checking + * is not performed when attr is NULL. + */ + +int pthread_mutex_init( + pthread_mutex_t *mutex, + const pthread_mutexattr_t *attr +) +{ + POSIX_Mutex_Control *the_mutex; + CORE_mutex_Attributes *the_mutex_attr; + const pthread_mutexattr_t *the_attr; + CORE_mutex_Disciplines the_discipline; + + if ( attr ) the_attr = attr; + else the_attr = &_POSIX_Mutex_Default_attributes; + + /* Check for NULL mutex */ + if ( !mutex ) + return EINVAL; + + /* + * This code should eventually be removed. + * + * Although the POSIX specification says: + * + * "Attempting to initialize an already initialized mutex results + * in undefined behavior." + * + * Trying to keep the caller from doing the create when *mutex + * is actually a valid ID causes grief. All it takes is the wrong + * value in an uninitialized variable to make this fail. As best + * I can tell, RTEMS was the only pthread implementation to choose + * this option for "undefined behavior" and doing so has created + * portability problems. In particular, Rosimildo DaSilva + * <rdasilva@connecttel.com> saw seemingly random failures in the + * RTEMS port of omniORB2 when this code was enabled. + * + * Joel Sherrill <joel@OARcorp.com> 14 May 1999 + * NOTE: Be careful to avoid infinite recursion on call to this + * routine in _POSIX_Mutex_Get. + */ + #if 0 + { + POSIX_Mutex_Control *mutex_in_use; + Objects_Locations location; + + if ( *mutex != PTHREAD_MUTEX_INITIALIZER ) { + + /* EBUSY if *mutex is a valid id */ + + mutex_in_use = _POSIX_Mutex_Get( mutex, &location ); + switch ( location ) { + case OBJECTS_LOCAL: + _Thread_Enable_dispatch(); + return EBUSY; + #if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: + #endif + case OBJECTS_ERROR: + break; + } + } + } + #endif + + if ( !the_attr->is_initialized ) + return EINVAL; + + /* + * We only support process private mutexes. + */ + if ( the_attr->process_shared == PTHREAD_PROCESS_SHARED ) + return ENOSYS; + + if ( the_attr->process_shared != PTHREAD_PROCESS_PRIVATE ) + return EINVAL; + + /* + * Determine the discipline of the mutex + */ + switch ( the_attr->protocol ) { + case PTHREAD_PRIO_NONE: + the_discipline = CORE_MUTEX_DISCIPLINES_FIFO; + break; + case PTHREAD_PRIO_INHERIT: + the_discipline = CORE_MUTEX_DISCIPLINES_PRIORITY_INHERIT; + break; + case PTHREAD_PRIO_PROTECT: + the_discipline = CORE_MUTEX_DISCIPLINES_PRIORITY_CEILING; + break; + default: + return EINVAL; + } + + /* + * Validate the priority ceiling field -- should always be valid. + */ + if ( !_POSIX_Priority_Is_valid( the_attr->prio_ceiling ) ) + return EINVAL; + +#if defined(_UNIX98_THREAD_MUTEX_ATTRIBUTES) + /* + * Validate the mutex type and set appropriate SuperCore mutex + * attributes. + */ + switch ( the_attr->type ) { + case PTHREAD_MUTEX_NORMAL: + case PTHREAD_MUTEX_RECURSIVE: + case PTHREAD_MUTEX_ERRORCHECK: + case PTHREAD_MUTEX_DEFAULT: + break; + + default: + return EINVAL; + } +#endif + + /* + * Enter a dispatching critical section and begin to do the real work. + */ + _Thread_Disable_dispatch(); + + the_mutex = _POSIX_Mutex_Allocate(); + + if ( !the_mutex ) { + _Thread_Enable_dispatch(); + return EAGAIN; + } + + the_mutex->process_shared = the_attr->process_shared; + + the_mutex_attr = &the_mutex->Mutex.Attributes; + + if ( the_attr->recursive ) + the_mutex_attr->lock_nesting_behavior = CORE_MUTEX_NESTING_ACQUIRES; + else + the_mutex_attr->lock_nesting_behavior = CORE_MUTEX_NESTING_IS_ERROR; + the_mutex_attr->only_owner_release = true; + the_mutex_attr->priority_ceiling = + _POSIX_Priority_To_core( the_attr->prio_ceiling ); + the_mutex_attr->discipline = the_discipline; + + /* + * Must be initialized to unlocked. + */ + _CORE_mutex_Initialize( + &the_mutex->Mutex, + the_mutex_attr, + CORE_MUTEX_UNLOCKED + ); + + _Objects_Open_u32( &_POSIX_Mutex_Information, &the_mutex->Object, 0 ); + + *mutex = the_mutex->Object.id; + + _Thread_Enable_dispatch(); + return 0; +} diff --git a/cpukit/posix/src/mutexlock.c b/cpukit/posix/src/mutexlock.c new file mode 100644 index 0000000000..85d1bd623b --- /dev/null +++ b/cpukit/posix/src/mutexlock.c @@ -0,0 +1,41 @@ +/* + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <errno.h> +#include <pthread.h> + +#include <rtems/system.h> +#include <rtems/score/coremutex.h> +#include <rtems/score/watchdog.h> +#if defined(RTEMS_MULTIPROCESSING) +#include <rtems/score/mpci.h> +#endif +#include <rtems/posix/mutex.h> +#include <rtems/posix/priority.h> +#include <rtems/posix/time.h> + +/*PAGE + * + * 11.3.3 Locking and Unlocking a Mutex, P1003.1c/Draft 10, p. 93 + * + * NOTE: P1003.4b/D8 adds pthread_mutex_timedlock(), p. 29 + */ + +int pthread_mutex_lock( + pthread_mutex_t *mutex +) +{ + return _POSIX_Mutex_Lock_support( mutex, true, THREAD_QUEUE_WAIT_FOREVER ); +} diff --git a/cpukit/posix/src/mutexlocksupp.c b/cpukit/posix/src/mutexlocksupp.c new file mode 100644 index 0000000000..43c80d054e --- /dev/null +++ b/cpukit/posix/src/mutexlocksupp.c @@ -0,0 +1,70 @@ +/* + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <errno.h> +#include <pthread.h> + +#include <rtems/system.h> +#include <rtems/score/coremutex.h> +#include <rtems/score/watchdog.h> +#if defined(RTEMS_MULTIPROCESSING) +#include <rtems/score/mpci.h> +#endif +#include <rtems/posix/mutex.h> +#include <rtems/posix/priority.h> +#include <rtems/posix/time.h> + +/*PAGE + * + * _POSIX_Mutex_Lock_support + * + * A support routine which implements guts of the blocking, non-blocking, and + * timed wait version of mutex lock. + */ + +int _POSIX_Mutex_Lock_support( + pthread_mutex_t *mutex, + bool blocking, + Watchdog_Interval timeout +) +{ + register POSIX_Mutex_Control *the_mutex; + Objects_Locations location; + ISR_Level level; + + the_mutex = _POSIX_Mutex_Get_interrupt_disable( mutex, &location, &level ); + switch ( location ) { + + case OBJECTS_LOCAL: + _CORE_mutex_Seize( + &the_mutex->Mutex, + the_mutex->Object.id, + blocking, + timeout, + level + ); + return _POSIX_Mutex_Translate_core_mutex_return_code( + (CORE_mutex_Status) _Thread_Executing->Wait.return_code + ); + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: +#endif + case OBJECTS_ERROR: + break; + } + + return EINVAL; +} diff --git a/cpukit/posix/src/mutexsetprioceiling.c b/cpukit/posix/src/mutexsetprioceiling.c new file mode 100644 index 0000000000..f132b38e04 --- /dev/null +++ b/cpukit/posix/src/mutexsetprioceiling.c @@ -0,0 +1,91 @@ +/* + * COPYRIGHT (c) 1989-2009. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <errno.h> +#include <pthread.h> + +#include <rtems/system.h> +#include <rtems/score/coremutex.h> +#include <rtems/score/watchdog.h> +#include <rtems/posix/mutex.h> +#include <rtems/posix/priority.h> +#include <rtems/posix/time.h> + +/*PAGE + * + * 13.6.2 Change the Priority Ceiling of a Mutex, P1003.1c/Draft 10, p. 131 + */ + +int pthread_mutex_setprioceiling( + pthread_mutex_t *mutex, + int prioceiling, + int *old_ceiling +) +{ + register POSIX_Mutex_Control *the_mutex; + Objects_Locations location; + Priority_Control the_priority; + + if ( !old_ceiling ) + return EINVAL; + + if ( !_POSIX_Priority_Is_valid( prioceiling ) ) + return EINVAL; + + the_priority = _POSIX_Priority_To_core( prioceiling ); + + /* + * Must acquire the mutex before we can change it's ceiling. + * POSIX says block until we acquire it. + */ + (void) pthread_mutex_lock( mutex ); + + /* + * Do not worry about the return code from this. The Get operation + * will also fail if it is a bad id or was deleted between the two + * operations. + * + * NOTE: This makes it easier to get 100% binary coverage since the + * bad Id case is handled by the switch. + */ + the_mutex = _POSIX_Mutex_Get( mutex, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + *old_ceiling = _POSIX_Priority_From_core( + the_mutex->Mutex.Attributes.priority_ceiling + ); + the_mutex->Mutex.Attributes.priority_ceiling = the_priority; + /* + * We are required to unlock the mutex before we return. + */ + _CORE_mutex_Surrender( + &the_mutex->Mutex, + the_mutex->Object.id, + NULL + ); + _Thread_Enable_dispatch(); + + return 0; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: /* impossible to get here */ +#endif + case OBJECTS_ERROR: + break; + } + + return EINVAL; +} diff --git a/cpukit/posix/src/mutextimedlock.c b/cpukit/posix/src/mutextimedlock.c new file mode 100644 index 0000000000..7773d84af6 --- /dev/null +++ b/cpukit/posix/src/mutextimedlock.c @@ -0,0 +1,83 @@ +/* + * Mutex Timed Lock + */ + +/* + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <errno.h> +#include <pthread.h> + +#include <rtems/system.h> +#include <rtems/score/coremutex.h> +#include <rtems/score/watchdog.h> +#if defined(RTEMS_MULTIPROCESSING) +#include <rtems/score/mpci.h> +#endif +#include <rtems/posix/mutex.h> +#include <rtems/posix/priority.h> +#include <rtems/posix/time.h> + +/*PAGE + * + * 11.3.3 Locking and Unlocking a Mutex, P1003.1c/Draft 10, p. 93 + * + * NOTE: P1003.4b/D8 adds pthread_mutex_timedlock(), p. 29 + */ + +int pthread_mutex_timedlock( + pthread_mutex_t *mutex, + const struct timespec *abstime +) +{ + Watchdog_Interval ticks; + bool do_wait = true; + POSIX_Absolute_timeout_conversion_results_t status; + int lock_status; + + /* + * POSIX requires that blocking calls with timeouts that take + * an absolute timeout must ignore issues with the absolute + * time provided if the operation would otherwise succeed. + * So we check the abstime provided, and hold on to whether it + * is valid or not. If it isn't correct and in the future, + * then we do a polling operation and convert the UNSATISFIED + * status into the appropriate error. + * + * If the status is POSIX_ABSOLUTE_TIMEOUT_INVALID, + * POSIX_ABSOLUTE_TIMEOUT_IS_IN_PAST, or POSIX_ABSOLUTE_TIMEOUT_IS_NOW, + * then we should not wait. + */ + status = _POSIX_Absolute_timeout_to_ticks( abstime, &ticks ); + if ( status != POSIX_ABSOLUTE_TIMEOUT_IS_IN_FUTURE ) + do_wait = false; + + lock_status = _POSIX_Mutex_Lock_support( mutex, do_wait, ticks ); + /* + * This service only gives us the option to block. We used a polling + * attempt to lock if the abstime was not in the future. If we did + * not obtain the mutex, then not look at the status immediately, + * make sure the right reason is returned. + */ + if ( !do_wait && (lock_status == EBUSY) ) { + if ( status == POSIX_ABSOLUTE_TIMEOUT_INVALID ) + return EINVAL; + if ( status == POSIX_ABSOLUTE_TIMEOUT_IS_IN_PAST || + status == POSIX_ABSOLUTE_TIMEOUT_IS_NOW ) + return ETIMEDOUT; + } + + return lock_status; +} diff --git a/cpukit/posix/src/mutextranslatereturncode.c b/cpukit/posix/src/mutextranslatereturncode.c new file mode 100644 index 0000000000..48b9a9a199 --- /dev/null +++ b/cpukit/posix/src/mutextranslatereturncode.c @@ -0,0 +1,61 @@ +/* + * POSIX Mutex Error Translation + * + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/score/coremutex.h> + +/* + * _POSIX_Mutex_Translate_core_mutex_return_code + * + * Input parameters: + * the_mutex_status - mutex status code to translate + * + * Output parameters: + * status code - translated POSIX status code + * + */ + +static int _POSIX_Mutex_Return_codes[CORE_MUTEX_STATUS_LAST + 1] = { + 0, /* CORE_MUTEX_STATUS_SUCCESSFUL */ + EBUSY, /* CORE_MUTEX_STATUS_UNSATISFIED_NOWAIT */ + EDEADLK, /* CORE_MUTEX_STATUS_NESTING_NOT_ALLOWED */ + EPERM, /* CORE_MUTEX_STATUS_NOT_OWNER_OF_RESOURCE */ + EINVAL, /* CORE_MUTEX_WAS_DELETED */ + ETIMEDOUT, /* CORE_MUTEX_TIMEOUT */ +#ifdef __RTEMS_STRICT_ORDER_MUTEX__ + EDEADLK, /* CORE_MUTEX_RELEASE_NOT_ORDER */ +#endif + EINVAL /* CORE_MUTEX_STATUS_CEILING_VIOLATED */ +}; + + +int _POSIX_Mutex_Translate_core_mutex_return_code( + CORE_mutex_Status the_mutex_status +) +{ + /* + * Internal consistency check for bad status from SuperCore + */ + #if defined(RTEMS_DEBUG) + if ( the_mutex_status > CORE_MUTEX_STATUS_LAST ) + return EINVAL; + #endif + return _POSIX_Mutex_Return_codes[the_mutex_status]; +} diff --git a/cpukit/posix/src/mutextrylock.c b/cpukit/posix/src/mutextrylock.c new file mode 100644 index 0000000000..d44f216614 --- /dev/null +++ b/cpukit/posix/src/mutextrylock.c @@ -0,0 +1,41 @@ +/* + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <errno.h> +#include <pthread.h> + +#include <rtems/system.h> +#include <rtems/score/coremutex.h> +#include <rtems/score/watchdog.h> +#if defined(RTEMS_MULTIPROCESSING) +#include <rtems/score/mpci.h> +#endif +#include <rtems/posix/mutex.h> +#include <rtems/posix/priority.h> +#include <rtems/posix/time.h> + +/*PAGE + * + * 11.3.3 Locking and Unlocking a Mutex, P1003.1c/Draft 10, p. 93 + * + * NOTE: P1003.4b/D8 adds pthread_mutex_timedlock(), p. 29 + */ + +int pthread_mutex_trylock( + pthread_mutex_t *mutex +) +{ + return _POSIX_Mutex_Lock_support( mutex, false, THREAD_QUEUE_WAIT_FOREVER ); +} diff --git a/cpukit/posix/src/mutexunlock.c b/cpukit/posix/src/mutexunlock.c new file mode 100644 index 0000000000..cdcd03f50c --- /dev/null +++ b/cpukit/posix/src/mutexunlock.c @@ -0,0 +1,64 @@ +/* + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <errno.h> +#include <pthread.h> + +#include <rtems/system.h> +#include <rtems/score/coremutex.h> +#include <rtems/score/watchdog.h> +#if defined(RTEMS_MULTIPROCESSING) +#include <rtems/score/mpci.h> +#endif +#include <rtems/posix/mutex.h> +#include <rtems/posix/priority.h> +#include <rtems/posix/time.h> + +/*PAGE + * + * 11.3.3 Locking and Unlocking a Mutex, P1003.1c/Draft 10, p. 93 + * + * NOTE: P1003.4b/D8 adds pthread_mutex_timedlock(), p. 29 + */ + +int pthread_mutex_unlock( + pthread_mutex_t *mutex +) +{ + register POSIX_Mutex_Control *the_mutex; + Objects_Locations location; + CORE_mutex_Status status; + + the_mutex = _POSIX_Mutex_Get( mutex, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + status = _CORE_mutex_Surrender( + &the_mutex->Mutex, + the_mutex->Object.id, + NULL + ); + _Thread_Enable_dispatch(); + return _POSIX_Mutex_Translate_core_mutex_return_code( status ); + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: +#endif + case OBJECTS_ERROR: + break; + } + + return EINVAL; +} diff --git a/cpukit/posix/src/nanosleep.c b/cpukit/posix/src/nanosleep.c new file mode 100644 index 0000000000..dc81a378d5 --- /dev/null +++ b/cpukit/posix/src/nanosleep.c @@ -0,0 +1,107 @@ +/* + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <time.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/score/isr.h> +#include <rtems/score/scheduler.h> +#include <rtems/score/thread.h> +#include <rtems/score/tod.h> + +#include <rtems/seterr.h> +#include <rtems/score/timespec.h> + +/*PAGE + * + * 14.2.5 High Resolution Sleep, P1003.1b-1993, p. 269 + */ + +int nanosleep( + const struct timespec *rqtp, + struct timespec *rmtp +) +{ + Watchdog_Interval ticks; + + + /* + * Return EINVAL if the delay interval is negative. + * + * NOTE: This behavior is beyond the POSIX specification. + * FSU and GNU/Linux pthreads shares this behavior. + */ + if ( !_Timespec_Is_valid( rqtp ) ) + rtems_set_errno_and_return_minus_one( EINVAL ); + + ticks = _Timespec_To_ticks( rqtp ); + + /* + * A nanosleep for zero time is implemented as a yield. + * This behavior is also beyond the POSIX specification but is + * consistent with the RTEMS API and yields desirable behavior. + */ + + if ( !ticks ) { + _Thread_Disable_dispatch(); + _Scheduler_Yield(); + _Thread_Enable_dispatch(); + if ( rmtp ) { + rmtp->tv_sec = 0; + rmtp->tv_nsec = 0; + } + return 0; + } + + /* + * Block for the desired amount of time + */ + _Thread_Disable_dispatch(); + _Thread_Set_state( + _Thread_Executing, + STATES_DELAYING | STATES_INTERRUPTIBLE_BY_SIGNAL + ); + _Watchdog_Initialize( + &_Thread_Executing->Timer, + _Thread_Delay_ended, + _Thread_Executing->Object.id, + NULL + ); + _Watchdog_Insert_ticks( &_Thread_Executing->Timer, ticks ); + _Thread_Enable_dispatch(); + + /* calculate time remaining */ + + if ( rmtp ) { + ticks -= + _Thread_Executing->Timer.stop_time - _Thread_Executing->Timer.start_time; + + _Timespec_From_ticks( ticks, rmtp ); + + /* + * Only when POSIX is enabled, can a sleep be interrupted. + */ + #if defined(RTEMS_POSIX_API) + /* + * If there is time remaining, then we were interrupted by a signal. + */ + if ( ticks ) + rtems_set_errno_and_return_minus_one( EINTR ); + #endif + } + + return 0; +} diff --git a/cpukit/posix/src/pause.c b/cpukit/posix/src/pause.c new file mode 100644 index 0000000000..e4a8782bc4 --- /dev/null +++ b/cpukit/posix/src/pause.c @@ -0,0 +1,40 @@ +/* + * 3.4.2 Suspend Process Execution, P1003.1b-1993, p. 81 + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <signal.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/pthread.h> +#include <rtems/posix/psignal.h> + +/* + * 3.4.2 Suspend Process Execution, P1003.1b-1993, p. 81 + */ + +int pause( void ) +{ + sigset_t all_signals; + int status; + + (void) sigfillset( &all_signals ); + + status = sigtimedwait( &all_signals, NULL, NULL ); + + return status; +} diff --git a/cpukit/posix/src/pbarrier.c b/cpukit/posix/src/pbarrier.c new file mode 100644 index 0000000000..d131000e89 --- /dev/null +++ b/cpukit/posix/src/pbarrier.c @@ -0,0 +1,57 @@ +/* + * Barrier Manager + * + * DESCRIPTION: + * + * This package is the implementation of the Barrier Manager. + * + * Directives provided are: + * + * + create a barrier + * + get an ID of a barrier + * + delete a barrier + * + acquire a barrier + * + release a barrier + * + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <limits.h> + +#include <rtems/system.h> +#include <rtems/config.h> +#include <rtems/posix/barrier.h> + +/** + * @brief _POSIX_Barrier_Manager_initialization + */ + +void _POSIX_Barrier_Manager_initialization(void) +{ + _Objects_Initialize_information( + &_POSIX_Barrier_Information, /* object information table */ + OBJECTS_POSIX_API, /* object API */ + OBJECTS_POSIX_BARRIERS, /* object class */ + Configuration_POSIX_API.maximum_barriers, + /* maximum objects of this class */ + sizeof( POSIX_Barrier_Control ),/* size of this object's control block */ + true, /* true if the name is a string */ + _POSIX_PATH_MAX /* maximum length of each object's name */ +#if defined(RTEMS_MULTIPROCESSING) + , + false, /* true if this is a global object class */ + NULL /* Proxy extraction support callout */ +#endif + ); +} diff --git a/cpukit/posix/src/pbarrierdestroy.c b/cpukit/posix/src/pbarrierdestroy.c new file mode 100644 index 0000000000..0caf8a1586 --- /dev/null +++ b/cpukit/posix/src/pbarrierdestroy.c @@ -0,0 +1,73 @@ +/* + * POSIX Barrier Manager -- Destroy a Barrier + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/barrier.h> + +/* + * pthread_barrier_destroy + * + * This directive allows a thread to delete a barrier specified by + * the barrier id. The barrier is freed back to the inactive + * barrier chain. + * + * Input parameters: + * barrier - barrier id + * + * Output parameters: + * 0 - if successful + * error code - if unsuccessful + */ + +int pthread_barrier_destroy( + pthread_barrier_t *barrier +) +{ + POSIX_Barrier_Control *the_barrier = NULL; + Objects_Locations location; + + if ( !barrier ) + return EINVAL; + + the_barrier = _POSIX_Barrier_Get( barrier, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + if ( the_barrier->Barrier.number_of_waiting_threads != 0 ) { + _Thread_Enable_dispatch(); + return EBUSY; + } + + _Objects_Close( &_POSIX_Barrier_Information, &the_barrier->Object ); + + _POSIX_Barrier_Free( the_barrier ); + + _Thread_Enable_dispatch(); + return 0; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: +#endif + case OBJECTS_ERROR: + break; + } + + return EINVAL; +} diff --git a/cpukit/posix/src/pbarrierinit.c b/cpukit/posix/src/pbarrierinit.c new file mode 100644 index 0000000000..a2a77f83a5 --- /dev/null +++ b/cpukit/posix/src/pbarrierinit.c @@ -0,0 +1,116 @@ +/* + * POSIX Barrier Manager -- Initialize a Barrier Instance + * + * COPYRIGHT (c) 1989-2006. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/barrier.h> + +/* + * pthread_barrier_init + * + * This directive creates a barrier. A barrier id is returned. + * + * Input parameters: + * barrier - pointer to barrier id + * attr - barrier attributes + * count - number of threads before automatic release + * + * Output parameters: + * barrier - barrier id + * 0 - if successful + * error code - if unsuccessful + */ + +int pthread_barrier_init( + pthread_barrier_t *barrier, + const pthread_barrierattr_t *attr, + unsigned int count +) +{ + POSIX_Barrier_Control *the_barrier; + CORE_barrier_Attributes the_attributes; + pthread_barrierattr_t my_attr; + const pthread_barrierattr_t *the_attr; + + /* + * Error check parameters + */ + if ( !barrier ) + return EINVAL; + + if ( count == 0 ) + return EINVAL; + + /* + * If the user passed in NULL, use the default attributes + */ + if ( attr ) { + the_attr = attr; + } else { + (void) pthread_barrierattr_init( &my_attr ); + the_attr = &my_attr; + } + + /* + * Now start error checking the attributes that we are going to use + */ + if ( !the_attr->is_initialized ) + return EINVAL; + + switch ( the_attr->process_shared ) { + case PTHREAD_PROCESS_PRIVATE: /* only supported values */ + break; + case PTHREAD_PROCESS_SHARED: + default: + return EINVAL; + } + + /* + * Convert from POSIX attributes to Core Barrier attributes + */ + the_attributes.discipline = CORE_BARRIER_AUTOMATIC_RELEASE; + the_attributes.maximum_count = count; + + /* + * Enter dispatching critical section to allocate and initialize barrier + */ + _Thread_Disable_dispatch(); /* prevents deletion */ + + the_barrier = _POSIX_Barrier_Allocate(); + + if ( !the_barrier ) { + _Thread_Enable_dispatch(); + return EAGAIN; + } + + _CORE_barrier_Initialize( &the_barrier->Barrier, &the_attributes ); + + _Objects_Open_u32( + &_POSIX_Barrier_Information, + &the_barrier->Object, + 0 + ); + + /* + * Exit the critical section and return the user an operational barrier + */ + *barrier = the_barrier->Object.id; + _Thread_Enable_dispatch(); + return 0; +} diff --git a/cpukit/posix/src/pbarriertranslatereturncode.c b/cpukit/posix/src/pbarriertranslatereturncode.c new file mode 100644 index 0000000000..0351fc5a65 --- /dev/null +++ b/cpukit/posix/src/pbarriertranslatereturncode.c @@ -0,0 +1,56 @@ +/* + * Barrier Manager -- Translate SuperCore Status + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/barrier.h> + +/* + * _POSIX_Barrier_Translate_core_barrier_return_code + * + * Input parameters: + * the_barrier_status - barrier status code to translate + * + * Output parameters: + * status code - translated POSIX status code + * + */ + +static int _POSIX_Barrier_Return_codes[CORE_BARRIER_STATUS_LAST + 1] = { + 0, /* CORE_BARRIER_STATUS_SUCCESSFUL */ + PTHREAD_BARRIER_SERIAL_THREAD, + /* CORE_BARRIER_STATUS_AUTOMATICALLY_RELEASED */ + -1, /* CORE_BARRIER_WAS_DELETED */ + 0 /* CORE_BARRIER_TIMEOUT */ +}; + + +int _POSIX_Barrier_Translate_core_barrier_return_code( + CORE_barrier_Status the_barrier_status +) +{ + /* + * Internal consistency check for bad status from SuperCore + */ + #if defined(RTEMS_DEBUG) + if ( the_barrier_status > CORE_BARRIER_STATUS_LAST ) + return EINVAL; + #endif + return _POSIX_Barrier_Return_codes[the_barrier_status]; +} diff --git a/cpukit/posix/src/pbarrierwait.c b/cpukit/posix/src/pbarrierwait.c new file mode 100644 index 0000000000..71533b65b1 --- /dev/null +++ b/cpukit/posix/src/pbarrierwait.c @@ -0,0 +1,71 @@ +/* + * POSIX Barrier Manager -- Wait at a Barrier + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/barrier.h> + +/* + * pthread_barrier_wait + * + * This directive allows a thread to wait at a barrier. + * + * Input parameters: + * barrier - barrier id + * + * Output parameters: + * 0 - if successful + * PTHREAD_BARRIER_SERIAL_THREAD - if successful + * error code - if unsuccessful + */ + +int pthread_barrier_wait( + pthread_barrier_t *barrier +) +{ + POSIX_Barrier_Control *the_barrier = NULL; + Objects_Locations location; + + if ( !barrier ) + return EINVAL; + + the_barrier = _POSIX_Barrier_Get( barrier, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + _CORE_barrier_Wait( + &the_barrier->Barrier, + the_barrier->Object.id, + true, + 0, + NULL + ); + _Thread_Enable_dispatch(); + return _POSIX_Barrier_Translate_core_barrier_return_code( + _Thread_Executing->Wait.return_code ); + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: +#endif + case OBJECTS_ERROR: + break; + } + + return EINVAL; +} diff --git a/cpukit/posix/src/posixtimespecabsolutetimeout.c b/cpukit/posix/src/posixtimespecabsolutetimeout.c new file mode 100644 index 0000000000..27d5db5abe --- /dev/null +++ b/cpukit/posix/src/posixtimespecabsolutetimeout.c @@ -0,0 +1,88 @@ +/* + * Convert abstime timeout to ticks + */ + +/* + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdarg.h> + +#include <errno.h> +#include <fcntl.h> +#include <pthread.h> +#include <semaphore.h> +#include <limits.h> + +#include <rtems/system.h> +#include <rtems/score/object.h> +#include <rtems/posix/semaphore.h> +#include <rtems/posix/time.h> +#include <rtems/seterr.h> + +/* + * The abstime is a walltime. We turn it into an interval. + */ +POSIX_Absolute_timeout_conversion_results_t _POSIX_Absolute_timeout_to_ticks( + const struct timespec *abstime, + Watchdog_Interval *ticks_out +) +{ + struct timespec current_time; + struct timespec difference; + + + /* + * Make sure there is always a value returned. + */ + *ticks_out = 0; + + /* + * Is the absolute time even valid? + */ + if ( !_Timespec_Is_valid(abstime) ) + return POSIX_ABSOLUTE_TIMEOUT_INVALID; + + /* + * Is the absolute time in the past? + */ + _TOD_Get( ¤t_time ); + + if ( _Timespec_Less_than( abstime, ¤t_time ) ) + return POSIX_ABSOLUTE_TIMEOUT_IS_IN_PAST; + + /* + * How long until the requested absolute time? + */ + _Timespec_Subtract( ¤t_time, abstime, &difference ); + + /* + * Internally the SuperCore uses ticks, so convert to them. + */ + *ticks_out = _Timespec_To_ticks( &difference ); + + /* + * If the difference was 0, then the future is now. It is so bright + * we better wear shades. + */ + if ( !*ticks_out ) + return POSIX_ABSOLUTE_TIMEOUT_IS_NOW; + + /* + * This is the case we were expecting and it took this long to + * get here. + */ + return POSIX_ABSOLUTE_TIMEOUT_IS_IN_FUTURE; +} + diff --git a/cpukit/posix/src/prwlock.c b/cpukit/posix/src/prwlock.c new file mode 100644 index 0000000000..9c3fd707d8 --- /dev/null +++ b/cpukit/posix/src/prwlock.c @@ -0,0 +1,45 @@ +/* + * RWLock Manager -- Initialization + * + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <limits.h> + +#include <rtems/system.h> +#include <rtems/config.h> +#include <rtems/posix/rwlock.h> + +/** + * @brief _POSIX_RWLock_Manager_initialization + */ + +void _POSIX_RWLock_Manager_initialization(void) +{ + _Objects_Initialize_information( + &_POSIX_RWLock_Information, /* object information table */ + OBJECTS_POSIX_API, /* object API */ + OBJECTS_POSIX_SPINLOCKS, /* object class */ + Configuration_POSIX_API.maximum_rwlocks, + /* maximum objects of this class */ + sizeof( POSIX_RWLock_Control ), /* size of this object's control block */ + true, /* true if the name is a string */ + _POSIX_PATH_MAX /* maximum length of each object's name */ +#if defined(RTEMS_MULTIPROCESSING) + , + false, /* true if this is a global object class */ + NULL /* Proxy extraction support callout */ +#endif + ); +} diff --git a/cpukit/posix/src/prwlockdestroy.c b/cpukit/posix/src/prwlockdestroy.c new file mode 100644 index 0000000000..8b32517c37 --- /dev/null +++ b/cpukit/posix/src/prwlockdestroy.c @@ -0,0 +1,80 @@ +/* + * POSIX RWLock Manager -- Destroy a RWLock + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/rwlock.h> + +/* + * pthread_rwlock_destroy + * + * This directive allows a thread to delete a rwlock specified by + * the rwlock id. The rwlock is freed back to the inactive + * rwlock chain. + * + * Input parameters: + * rwlock - rwlock id + * + * Output parameters: + * 0 - if successful + * error code - if unsuccessful + */ + +int pthread_rwlock_destroy( + pthread_rwlock_t *rwlock +) +{ + POSIX_RWLock_Control *the_rwlock = NULL; + Objects_Locations location; + + if ( !rwlock ) + return EINVAL; + + the_rwlock = _POSIX_RWLock_Get( rwlock, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + /* + * If there is at least one thread waiting, then do not delete it. + */ + if ( _Thread_queue_First( &the_rwlock->RWLock.Wait_queue ) != NULL ) { + _Thread_Enable_dispatch(); + return EBUSY; + } + + /* + * POSIX doesn't require behavior when it is locked. + */ + + _Objects_Close( &_POSIX_RWLock_Information, &the_rwlock->Object ); + + _POSIX_RWLock_Free( the_rwlock ); + + _Thread_Enable_dispatch(); + return 0; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: +#endif + case OBJECTS_ERROR: + break; + } + + return EINVAL; +} diff --git a/cpukit/posix/src/prwlockinit.c b/cpukit/posix/src/prwlockinit.c new file mode 100644 index 0000000000..c79b260b50 --- /dev/null +++ b/cpukit/posix/src/prwlockinit.c @@ -0,0 +1,110 @@ +/* + * POSIX RWLock Manager -- Destroy a RWLock Instance + * + * COPYRIGHT (c) 1989-2006. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/rwlock.h> + +/* + * pthread_rwlock_init + * + * This directive creates a rwlock. A rwlock id is returned. + * + * Input parameters: + * rwlock - pointer to rwlock id + * attr - rwlock attributes + * + * Output parameters: + * rwlock - rwlock id + * 0 - if successful + * error code - if unsuccessful + */ + +int pthread_rwlock_init( + pthread_rwlock_t *rwlock, + const pthread_rwlockattr_t *attr +) +{ + POSIX_RWLock_Control *the_rwlock; + CORE_RWLock_Attributes the_attributes; + pthread_rwlockattr_t default_attr; + const pthread_rwlockattr_t *the_attr; + + /* + * Error check parameters + */ + if ( !rwlock ) + return EINVAL; + + /* + * If the user passed in NULL, use the default attributes + */ + if ( attr ) { + the_attr = attr; + } else { + (void) pthread_rwlockattr_init( &default_attr ); + the_attr = &default_attr; + } + + /* + * Now start error checking the attributes that we are going to use + */ + if ( !the_attr->is_initialized ) + return EINVAL; + + switch ( the_attr->process_shared ) { + case PTHREAD_PROCESS_PRIVATE: /* only supported values */ + break; + case PTHREAD_PROCESS_SHARED: + default: + return EINVAL; + } + + /* + * Convert from POSIX attributes to Core RWLock attributes + * + * NOTE: Currently there are no core rwlock attributes + */ + _CORE_RWLock_Initialize_attributes( &the_attributes ); + + /* + * Enter dispatching critical section to allocate and initialize RWLock + */ + _Thread_Disable_dispatch(); /* prevents deletion */ + + the_rwlock = _POSIX_RWLock_Allocate(); + + if ( !the_rwlock ) { + _Thread_Enable_dispatch(); + return EAGAIN; + } + + _CORE_RWLock_Initialize( &the_rwlock->RWLock, &the_attributes ); + + _Objects_Open_u32( + &_POSIX_RWLock_Information, + &the_rwlock->Object, + 0 + ); + + *rwlock = the_rwlock->Object.id; + + _Thread_Enable_dispatch(); + return 0; +} diff --git a/cpukit/posix/src/prwlockrdlock.c b/cpukit/posix/src/prwlockrdlock.c new file mode 100644 index 0000000000..fe9d6196d9 --- /dev/null +++ b/cpukit/posix/src/prwlockrdlock.c @@ -0,0 +1,73 @@ +/* + * POSIX RWLock Manager -- Obtain a Read Lock on a RWLock Instance + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/rwlock.h> + +/* + * pthread_rwlock_rdlock + * + * This directive attempts to obtain a read only lock on an rwlock instance. + * + * Input parameters: + * rwlock - pointer to rwlock id + * + * Output parameters: + * 0 - if successful + * error code - if unsuccessful + */ + +int pthread_rwlock_rdlock( + pthread_rwlock_t *rwlock +) +{ + POSIX_RWLock_Control *the_rwlock; + Objects_Locations location; + + if ( !rwlock ) + return EINVAL; + + the_rwlock = _POSIX_RWLock_Get( rwlock, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + + _CORE_RWLock_Obtain_for_reading( + &the_rwlock->RWLock, + *rwlock, + true, /* we are willing to wait forever */ + 0, + NULL + ); + + _Thread_Enable_dispatch(); + return _POSIX_RWLock_Translate_core_RWLock_return_code( + (CORE_RWLock_Status) _Thread_Executing->Wait.return_code + ); + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: +#endif + case OBJECTS_ERROR: + break; + } + + return EINVAL; +} diff --git a/cpukit/posix/src/prwlocktimedrdlock.c b/cpukit/posix/src/prwlocktimedrdlock.c new file mode 100644 index 0000000000..d6df7815a8 --- /dev/null +++ b/cpukit/posix/src/prwlocktimedrdlock.c @@ -0,0 +1,105 @@ +/* + * POSIX RWLock Manager -- Attempt to Obtain a Read Lock on a RWLock Instance + * + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/rwlock.h> +#include <rtems/posix/time.h> + +/* + * pthread_rwlock_timedrdlock + * + * This directive attempts to obtain a read only lock on an rwlock instance. + * + * Input parameters: + * rwlock - pointer to rwlock id + * + * Output parameters: + * 0 - if successful + * error code - if unsuccessful + */ + +int pthread_rwlock_timedrdlock( + pthread_rwlock_t *rwlock, + const struct timespec *abstime +) +{ + POSIX_RWLock_Control *the_rwlock; + Objects_Locations location; + Watchdog_Interval ticks; + bool do_wait = true; + POSIX_Absolute_timeout_conversion_results_t status; + + if ( !rwlock ) + return EINVAL; + + /* + * POSIX requires that blocking calls with timeouts that take + * an absolute timeout must ignore issues with the absolute + * time provided if the operation would otherwise succeed. + * So we check the abstime provided, and hold on to whether it + * is valid or not. If it isn't correct and in the future, + * then we do a polling operation and convert the UNSATISFIED + * status into the appropriate error. + * + * If the status is POSIX_ABSOLUTE_TIMEOUT_INVALID, + * POSIX_ABSOLUTE_TIMEOUT_IS_IN_PAST, or POSIX_ABSOLUTE_TIMEOUT_IS_NOW, + * then we should not wait. + */ + status = _POSIX_Absolute_timeout_to_ticks( abstime, &ticks ); + if ( status != POSIX_ABSOLUTE_TIMEOUT_IS_IN_FUTURE ) + do_wait = false; + + the_rwlock = _POSIX_RWLock_Get( rwlock, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + + _CORE_RWLock_Obtain_for_reading( + &the_rwlock->RWLock, + *rwlock, + do_wait, + ticks, + NULL + ); + + _Thread_Enable_dispatch(); + if ( !do_wait ) { + if ( _Thread_Executing->Wait.return_code == CORE_RWLOCK_UNAVAILABLE ) { + if ( status == POSIX_ABSOLUTE_TIMEOUT_INVALID ) + return EINVAL; + if ( status == POSIX_ABSOLUTE_TIMEOUT_IS_IN_PAST || + status == POSIX_ABSOLUTE_TIMEOUT_IS_NOW ) + return ETIMEDOUT; + } + } + + return _POSIX_RWLock_Translate_core_RWLock_return_code( + (CORE_RWLock_Status) _Thread_Executing->Wait.return_code + ); + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: +#endif + case OBJECTS_ERROR: + break; + } + + return EINVAL; +} diff --git a/cpukit/posix/src/prwlocktimedwrlock.c b/cpukit/posix/src/prwlocktimedwrlock.c new file mode 100644 index 0000000000..d34ee69489 --- /dev/null +++ b/cpukit/posix/src/prwlocktimedwrlock.c @@ -0,0 +1,104 @@ +/* + * POSIX RWLock Manager -- Attempt to Obtain a Write Lock on a RWLock Instance + * + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/rwlock.h> +#include <rtems/posix/time.h> + +/* + * pthread_rwlock_timedwrlock + * + * This directive attempts to obtain a write only lock on an rwlock instance. + * + * Input parameters: + * rwlock - pointer to rwlock id + * + * Output parameters: + * 0 - if successful + * error code - if unsuccessful + */ + +int pthread_rwlock_timedwrlock( + pthread_rwlock_t *rwlock, + const struct timespec *abstime +) +{ + POSIX_RWLock_Control *the_rwlock; + Objects_Locations location; + Watchdog_Interval ticks; + bool do_wait = true; + POSIX_Absolute_timeout_conversion_results_t status; + + if ( !rwlock ) + return EINVAL; + + /* + * POSIX requires that blocking calls with timeouts that take + * an absolute timeout must ignore issues with the absolute + * time provided if the operation would otherwise succeed. + * So we check the abstime provided, and hold on to whether it + * is valid or not. If it isn't correct and in the future, + * then we do a polling operation and convert the UNSATISFIED + * status into the appropriate error. + * + * If the status is POSIX_ABSOLUTE_TIMEOUT_INVALID, + * POSIX_ABSOLUTE_TIMEOUT_IS_IN_PAST, or POSIX_ABSOLUTE_TIMEOUT_IS_NOW, + * then we should not wait. + */ + status = _POSIX_Absolute_timeout_to_ticks( abstime, &ticks ); + if ( status != POSIX_ABSOLUTE_TIMEOUT_IS_IN_FUTURE ) + do_wait = false; + + the_rwlock = _POSIX_RWLock_Get( rwlock, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + + _CORE_RWLock_Obtain_for_writing( + &the_rwlock->RWLock, + *rwlock, + do_wait, + ticks, + NULL + ); + + _Thread_Enable_dispatch(); + if ( !do_wait && + (_Thread_Executing->Wait.return_code == CORE_RWLOCK_UNAVAILABLE) ) { + if ( status == POSIX_ABSOLUTE_TIMEOUT_INVALID ) + return EINVAL; + if ( status == POSIX_ABSOLUTE_TIMEOUT_IS_IN_PAST || + status == POSIX_ABSOLUTE_TIMEOUT_IS_NOW ) + return ETIMEDOUT; + } + + return _POSIX_RWLock_Translate_core_RWLock_return_code( + (CORE_RWLock_Status) _Thread_Executing->Wait.return_code + ); + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: +#endif + case OBJECTS_ERROR: + break; + } + + return EINVAL; +} diff --git a/cpukit/posix/src/prwlocktranslatereturncode.c b/cpukit/posix/src/prwlocktranslatereturncode.c new file mode 100644 index 0000000000..3378d577b2 --- /dev/null +++ b/cpukit/posix/src/prwlocktranslatereturncode.c @@ -0,0 +1,55 @@ +/* + * RWLock Manager -- Translate SuperCore Status + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/rwlock.h> + +/* + * _POSIX_RWLock_Translate_core_rwlock_return_code + * + * Input parameters: + * the_rwlock_status - rwlock status code to translate + * + * Output parameters: + * status code - translated POSIX status code + * + */ + +static int _POSIX_RWLock_Return_codes[CORE_RWLOCK_STATUS_LAST + 1] = { + 0, /* CORE_RWLOCK_SUCCESSFUL */ + EINVAL, /* CORE_RWLOCK_DELETED */ + EBUSY, /* CORE_RWLOCK_UNAVAILABLE */ + ETIMEDOUT, /* CORE_RWLOCK_TIMEOUT */ +}; + + +int _POSIX_RWLock_Translate_core_RWLock_return_code( + CORE_RWLock_Status the_rwlock_status +) +{ + /* + * Internal consistency check for bad status from SuperCore + */ + #if defined(RTEMS_DEBUG) + if ( the_rwlock_status > CORE_RWLOCK_STATUS_LAST ) + return EINVAL; + #endif + return _POSIX_RWLock_Return_codes[the_rwlock_status]; +} diff --git a/cpukit/posix/src/prwlocktryrdlock.c b/cpukit/posix/src/prwlocktryrdlock.c new file mode 100644 index 0000000000..f07edf5f4d --- /dev/null +++ b/cpukit/posix/src/prwlocktryrdlock.c @@ -0,0 +1,74 @@ +/* + * POSIX RWLock Manager -- Attempt to Obtain a Read Lock on a RWLock Instance + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/rwlock.h> + +/* + * pthread_rwlock_tryrdlock + * + * This directive attempts to obtain a read only lock on an rwlock instance. + * + * Input parameters: + * rwlock - pointer to rwlock id + * + * Output parameters: + * 0 - if successful + * error code - if unsuccessful + */ + +int pthread_rwlock_tryrdlock( + pthread_rwlock_t *rwlock +) +{ + POSIX_RWLock_Control *the_rwlock; + Objects_Locations location; + + if ( !rwlock ) + return EINVAL; + + the_rwlock = _POSIX_RWLock_Get( rwlock, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + + _CORE_RWLock_Obtain_for_reading( + &the_rwlock->RWLock, + *rwlock, + false, /* do not wait for the rwlock */ + 0, + NULL + ); + + + _Thread_Enable_dispatch(); + return _POSIX_RWLock_Translate_core_RWLock_return_code( + (CORE_RWLock_Status) _Thread_Executing->Wait.return_code + ); + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: +#endif + case OBJECTS_ERROR: + break; + } + + return EINVAL; +} diff --git a/cpukit/posix/src/prwlocktrywrlock.c b/cpukit/posix/src/prwlocktrywrlock.c new file mode 100644 index 0000000000..326e643910 --- /dev/null +++ b/cpukit/posix/src/prwlocktrywrlock.c @@ -0,0 +1,73 @@ +/* + * POSIX RWLock Manager -- Attempt to Obtain a Write Lock on a RWLock Instance + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/rwlock.h> + +/* + * pthread_rwlock_trywrlock + * + * This directive attempts to obtain a Write only lock on an rwlock instance. + * + * Input parameters: + * rwlock - pointer to rwlock id + * + * Output parameters: + * 0 - if successful + * error code - if unsuccessful + */ + +int pthread_rwlock_trywrlock( + pthread_rwlock_t *rwlock +) +{ + POSIX_RWLock_Control *the_rwlock; + Objects_Locations location; + + if ( !rwlock ) + return EINVAL; + + the_rwlock = _POSIX_RWLock_Get( rwlock, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + + _CORE_RWLock_Obtain_for_writing( + &the_rwlock->RWLock, + *rwlock, + false, /* we are not willing to wait */ + 0, + NULL + ); + + _Thread_Enable_dispatch(); + return _POSIX_RWLock_Translate_core_RWLock_return_code( + (CORE_RWLock_Status) _Thread_Executing->Wait.return_code + ); + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: +#endif + case OBJECTS_ERROR: + break; + } + + return EINVAL; +} diff --git a/cpukit/posix/src/prwlockunlock.c b/cpukit/posix/src/prwlockunlock.c new file mode 100644 index 0000000000..665ee1fb34 --- /dev/null +++ b/cpukit/posix/src/prwlockunlock.c @@ -0,0 +1,64 @@ +/* + * POSIX RWLock Manager -- Release a lock held on a RWLock Instance + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/rwlock.h> + +/* + * pthread_rwlock_unlock + * + * This directive attempts to release a lock on an RWLock. + * + * Input parameters: + * rwlock - pointer to rwlock id + * + * Output parameters: + * 0 - if successful + * error code - if unsuccessful + */ + +int pthread_rwlock_unlock( + pthread_rwlock_t *rwlock +) +{ + POSIX_RWLock_Control *the_rwlock; + Objects_Locations location; + CORE_RWLock_Status status; + + if ( !rwlock ) + return EINVAL; + + the_rwlock = _POSIX_RWLock_Get( rwlock, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + status = _CORE_RWLock_Release( &the_rwlock->RWLock ); + _Thread_Enable_dispatch(); + return _POSIX_RWLock_Translate_core_RWLock_return_code( status ); + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: +#endif + case OBJECTS_ERROR: + break; + } + + return EINVAL; +} diff --git a/cpukit/posix/src/prwlockwrlock.c b/cpukit/posix/src/prwlockwrlock.c new file mode 100644 index 0000000000..61d5facbef --- /dev/null +++ b/cpukit/posix/src/prwlockwrlock.c @@ -0,0 +1,73 @@ +/* + * POSIX RWLock Manager -- Obtain a Write Lock on a RWLock Instance + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/rwlock.h> + +/* + * pthread_rwlock_wrlock + * + * This directive attempts to obtain a write only lock on an rwlock instance. + * + * Input parameters: + * rwlock - pointer to rwlock id + * + * Output parameters: + * 0 - if successful + * error code - if unsuccessful + */ + +int pthread_rwlock_wrlock( + pthread_rwlock_t *rwlock +) +{ + POSIX_RWLock_Control *the_rwlock; + Objects_Locations location; + + if ( !rwlock ) + return EINVAL; + + the_rwlock = _POSIX_RWLock_Get( rwlock, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + + _CORE_RWLock_Obtain_for_writing( + &the_rwlock->RWLock, + *rwlock, + true, /* do not timeout -- wait forever */ + 0, + NULL + ); + + _Thread_Enable_dispatch(); + return _POSIX_RWLock_Translate_core_RWLock_return_code( + (CORE_RWLock_Status) _Thread_Executing->Wait.return_code + ); + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: +#endif + case OBJECTS_ERROR: + break; + } + + return EINVAL; +} diff --git a/cpukit/posix/src/psignal.c b/cpukit/posix/src/psignal.c new file mode 100644 index 0000000000..3040718874 --- /dev/null +++ b/cpukit/posix/src/psignal.c @@ -0,0 +1,224 @@ +/* + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#if defined(RTEMS_DEBUG) + #include <assert.h> +#endif +#include <errno.h> +#include <pthread.h> +#include <signal.h> +#include <string.h> /* memcpy */ +#include <stdlib.h> /* exit */ + +#include <rtems/system.h> +#include <rtems/config.h> +#include <rtems/score/isr.h> +#include <rtems/score/thread.h> +#include <rtems/score/tqdata.h> +#include <rtems/score/wkspace.h> +#include <rtems/seterr.h> +#include <rtems/posix/threadsup.h> +#include <rtems/posix/psignal.h> +#include <rtems/posix/pthread.h> +#include <rtems/posix/time.h> +#include <stdio.h> + +/*** PROCESS WIDE STUFF ****/ + +sigset_t _POSIX_signals_Pending; + +void _POSIX_signals_Abnormal_termination_handler( + int signo __attribute__((unused)) ) +{ + exit( 1 ); +} + +#define SIG_ARRAY_MAX (SIGRTMAX + 1) +const struct sigaction _POSIX_signals_Default_vectors[ SIG_ARRAY_MAX ] = { + /* NO SIGNAL 0 */ SIGACTION_IGNORE, + /* SIGHUP 1 */ SIGACTION_TERMINATE, + /* SIGINT 2 */ SIGACTION_TERMINATE, + /* SIGQUIT 3 */ SIGACTION_TERMINATE, + /* SIGILL 4 */ SIGACTION_TERMINATE, + /* SIGTRAP 5 */ SIGACTION_TERMINATE, + /* SIGIOT 6 */ SIGACTION_TERMINATE, + /* SIGABRT 6 SIGACTION_TERMINATE, -- alias for SIGIOT */ + /* SIGEMT 7 */ SIGACTION_TERMINATE, + /* SIGFPE 8 */ SIGACTION_TERMINATE, + /* SIGKILL 9 */ SIGACTION_TERMINATE, + /* SIGBUS 10 */ SIGACTION_TERMINATE, + /* SIGSEGV 11 */ SIGACTION_TERMINATE, + /* SIGSYS 12 */ SIGACTION_TERMINATE, + /* SIGPIPE 13 */ SIGACTION_TERMINATE, + /* SIGALRM 14 */ SIGACTION_TERMINATE, + /* SIGTERM 15 */ SIGACTION_TERMINATE, + /* SIGURG 16 */ SIGACTION_TERMINATE, + /* SIGSTOP 17 */ SIGACTION_TERMINATE, + /* SIGTSTP 18 */ SIGACTION_TERMINATE, + /* SIGCONT 19 */ SIGACTION_TERMINATE, + /* SIGCHLD 20 */ SIGACTION_TERMINATE, + /* SIGTTIN 21 */ SIGACTION_TERMINATE, + /* SIGTTOU 22 */ SIGACTION_TERMINATE, + /* SIGIO 23 */ SIGACTION_TERMINATE, + /* SIGWINCH 24 */ SIGACTION_TERMINATE, + /* SIGUSR1 25 */ SIGACTION_TERMINATE, + /* SIGUSR2 26 */ SIGACTION_TERMINATE, + /* SIGRT 27 */ SIGACTION_TERMINATE, + /* SIGRT 28 */ SIGACTION_TERMINATE, + /* SIGRT 29 */ SIGACTION_TERMINATE, + /* SIGRT 30 */ SIGACTION_TERMINATE, + /* SIGRTMAX 31 */ SIGACTION_TERMINATE +}; + +struct sigaction _POSIX_signals_Vectors[ SIG_ARRAY_MAX ]; + +Thread_queue_Control _POSIX_signals_Wait_queue; + +Chain_Control _POSIX_signals_Inactive_siginfo; +Chain_Control _POSIX_signals_Siginfo[ SIG_ARRAY_MAX ]; + +Watchdog_Control _POSIX_signals_Alarm_timer; +Watchdog_Control _POSIX_signals_Ualarm_timer; + +/*PAGE + * + * XXX - move these + */ + +#define _States_Is_interruptible_signal( _states ) \ + ( ((_states) & \ + (STATES_WAITING_FOR_SIGNAL|STATES_INTERRUPTIBLE_BY_SIGNAL)) == \ + (STATES_WAITING_FOR_SIGNAL|STATES_INTERRUPTIBLE_BY_SIGNAL)) + +/* + * _POSIX_signals_Post_switch_extension + */ + +void _POSIX_signals_Post_switch_extension( + Thread_Control *the_thread +) +{ + POSIX_API_Control *api; + int signo; + ISR_Level level; + + api = the_thread->API_Extensions[ THREAD_API_POSIX ]; + + /* + * api may be NULL in case of a thread close in progress + */ + if ( !api ) + return; + + /* + * If we invoke any user code, there is the possibility that + * a new signal has been posted that we should process so we + * restart the loop if a signal handler was invoked. + * + * The first thing done is to check there are any signals to be + * processed at all. No point in doing this loop otherwise. + */ + while (1) { + _ISR_Disable( level ); + if ( !(~api->signals_blocked & + (api->signals_pending | _POSIX_signals_Pending)) ) { + _ISR_Enable( level ); + break; + } + _ISR_Enable( level ); + + for ( signo = SIGRTMIN ; signo <= SIGRTMAX ; signo++ ) { + _POSIX_signals_Check_signal( api, signo, false ); + _POSIX_signals_Check_signal( api, signo, true ); + } + /* Unfortunately - nothing like __SIGFIRSTNOTRT in newlib signal .h */ + + for ( signo = SIGHUP ; signo <= __SIGLASTNOTRT ; signo++ ) { + _POSIX_signals_Check_signal( api, signo, false ); + _POSIX_signals_Check_signal( api, signo, true ); + } + } +} + +/*PAGE + * + * _POSIX_signals_Manager_Initialization + */ + +void _POSIX_signals_Manager_Initialization(void) +{ + uint32_t signo; + uint32_t maximum_queued_signals; + + maximum_queued_signals = Configuration_POSIX_API.maximum_queued_signals; + + /* + * Ensure we have the same number of vectors and default vector entries + */ + + #if defined(RTEMS_DEBUG) + assert( + sizeof(_POSIX_signals_Vectors) == sizeof(_POSIX_signals_Default_vectors) + ); + #endif + + memcpy( + _POSIX_signals_Vectors, + _POSIX_signals_Default_vectors, + sizeof( _POSIX_signals_Vectors ) + ); + + /* + * Initialize the set of pending signals for the entire process + */ + sigemptyset( &_POSIX_signals_Pending ); + + /* + * Initialize the queue we use to block for signals + */ + _Thread_queue_Initialize( + &_POSIX_signals_Wait_queue, + THREAD_QUEUE_DISCIPLINE_FIFO, + STATES_WAITING_FOR_SIGNAL | STATES_INTERRUPTIBLE_BY_SIGNAL, + EAGAIN + ); + + /* XXX status codes */ + + /* + * Allocate the siginfo pools. + */ + for ( signo=1 ; signo<= SIGRTMAX ; signo++ ) + _Chain_Initialize_empty( &_POSIX_signals_Siginfo[ signo ] ); + + if ( maximum_queued_signals ) { + _Chain_Initialize( + &_POSIX_signals_Inactive_siginfo, + _Workspace_Allocate_or_fatal_error( + maximum_queued_signals * sizeof( POSIX_signals_Siginfo_node ) + ), + maximum_queued_signals, + sizeof( POSIX_signals_Siginfo_node ) + ); + } else { + _Chain_Initialize_empty( &_POSIX_signals_Inactive_siginfo ); + } + + /* + * Initialize the Alarm Timer + */ + _Watchdog_Initialize( &_POSIX_signals_Alarm_timer, NULL, 0, NULL ); + _Watchdog_Initialize( &_POSIX_signals_Ualarm_timer, NULL, 0, NULL ); +} diff --git a/cpukit/posix/src/psignalchecksignal.c b/cpukit/posix/src/psignalchecksignal.c new file mode 100644 index 0000000000..8bba7a4226 --- /dev/null +++ b/cpukit/posix/src/psignalchecksignal.c @@ -0,0 +1,113 @@ +/* + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#if defined(RTEMS_DEBUG) + #include <assert.h> +#endif +#include <errno.h> +#include <pthread.h> +#include <signal.h> +#include <string.h> + +#include <rtems/system.h> +#include <rtems/score/isr.h> +#include <rtems/score/thread.h> +#include <rtems/score/tqdata.h> +#include <rtems/score/wkspace.h> +#include <rtems/seterr.h> +#include <rtems/posix/threadsup.h> +#include <rtems/posix/psignal.h> +#include <rtems/posix/pthread.h> +#include <rtems/posix/time.h> +#include <stdio.h> + + +/*PAGE + * + * _POSIX_signals_Check_signal + */ + +bool _POSIX_signals_Check_signal( + POSIX_API_Control *api, + int signo, + bool is_global +) +{ + siginfo_t siginfo_struct; + sigset_t saved_signals_blocked; + Thread_Wait_information stored_thread_wait_information; + + if ( ! _POSIX_signals_Clear_signals( api, signo, &siginfo_struct, + is_global, true ) ) + return false; + + /* + * Since we made a union of these, only one test is necessary but this is + * safer. + */ + #if defined(RTEMS_DEBUG) + assert( _POSIX_signals_Vectors[ signo ].sa_handler || + _POSIX_signals_Vectors[ signo ].sa_sigaction ); + #endif + + /* + * Just to prevent sending a signal which is currently being ignored. + */ + if ( _POSIX_signals_Vectors[ signo ].sa_handler == SIG_IGN ) + return false; + + /* + * Block the signals requested in sa_mask + */ + saved_signals_blocked = api->signals_blocked; + api->signals_blocked |= _POSIX_signals_Vectors[ signo ].sa_mask; + + /* + * We have to save the blocking information of the current wait queue + * because the signal handler may subsequently go on and put the thread + * on a wait queue, for its own purposes. + */ + memcpy( &stored_thread_wait_information, &_Thread_Executing->Wait, + sizeof( Thread_Wait_information )); + + /* + * Here, the signal handler function executes + */ + switch ( _POSIX_signals_Vectors[ signo ].sa_flags ) { + case SA_SIGINFO: + (*_POSIX_signals_Vectors[ signo ].sa_sigaction)( + signo, + &siginfo_struct, + NULL /* context is undefined per 1003.1b-1993, p. 66 */ + ); + break; + default: + (*_POSIX_signals_Vectors[ signo ].sa_handler)( signo ); + break; + } + + /* + * Restore the blocking information + */ + memcpy( &_Thread_Executing->Wait, &stored_thread_wait_information, + sizeof( Thread_Wait_information )); + + /* + * Restore the previous set of blocked signals + */ + api->signals_blocked = saved_signals_blocked; + + return true; +} diff --git a/cpukit/posix/src/psignalclearprocesssignals.c b/cpukit/posix/src/psignalclearprocesssignals.c new file mode 100644 index 0000000000..b11ae0ebc2 --- /dev/null +++ b/cpukit/posix/src/psignalclearprocesssignals.c @@ -0,0 +1,58 @@ +/* + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <errno.h> +#include <pthread.h> +#include <signal.h> + +#include <rtems/system.h> +#include <rtems/score/isr.h> +#include <rtems/score/thread.h> +#include <rtems/score/tqdata.h> +#include <rtems/score/wkspace.h> +#include <rtems/seterr.h> +#include <rtems/posix/threadsup.h> +#include <rtems/posix/psignal.h> +#include <rtems/posix/pthread.h> +#include <rtems/posix/time.h> +#include <stdio.h> + +/*PAGE + * + * _POSIX_signals_Clear_process_signals + */ + +void _POSIX_signals_Clear_process_signals( + int signo +) +{ + sigset_t mask; + bool clear_signal; + + clear_signal = true; + mask = signo_to_mask( signo ); + + ISR_Level level; + + _ISR_Disable( level ); + if ( _POSIX_signals_Vectors[ signo ].sa_flags == SA_SIGINFO ) { + if ( !_Chain_Is_empty( &_POSIX_signals_Siginfo[ signo ] ) ) + clear_signal = false; + } + if ( clear_signal ) { + _POSIX_signals_Pending &= ~mask; + } + _ISR_Enable( level ); +} diff --git a/cpukit/posix/src/psignalclearsignals.c b/cpukit/posix/src/psignalclearsignals.c new file mode 100644 index 0000000000..09942f3bb5 --- /dev/null +++ b/cpukit/posix/src/psignalclearsignals.c @@ -0,0 +1,99 @@ +/* + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <errno.h> +#include <pthread.h> +#include <signal.h> + +#include <rtems/system.h> +#include <rtems/score/isr.h> +#include <rtems/score/thread.h> +#include <rtems/score/tqdata.h> +#include <rtems/score/wkspace.h> +#include <rtems/seterr.h> +#include <rtems/posix/threadsup.h> +#include <rtems/posix/psignal.h> +#include <rtems/posix/pthread.h> +#include <rtems/posix/time.h> +#include <stdio.h> + +/*PAGE + * + * _POSIX_signals_Clear_signals + */ + +bool _POSIX_signals_Clear_signals( + POSIX_API_Control *api, + int signo, + siginfo_t *info, + bool is_global, + bool check_blocked +) +{ + sigset_t mask; + sigset_t signals_blocked; + ISR_Level level; + bool do_callout; + POSIX_signals_Siginfo_node *psiginfo; + + mask = signo_to_mask( signo ); + + do_callout = false; + + /* set blocked signals based on if checking for them, SIGNAL_ALL_MASK + * insures that no signals are blocked and all are checked. + */ + + if ( check_blocked ) + signals_blocked = ~api->signals_blocked; + else + signals_blocked = SIGNAL_ALL_MASK; + + /* XXX is this right for siginfo type signals? */ + /* XXX are we sure they can be cleared the same way? */ + + _ISR_Disable( level ); + if ( is_global ) { + if ( mask & (_POSIX_signals_Pending & signals_blocked) ) { + if ( _POSIX_signals_Vectors[ signo ].sa_flags == SA_SIGINFO ) { + psiginfo = (POSIX_signals_Siginfo_node *) + _Chain_Get_unprotected( &_POSIX_signals_Siginfo[ signo ] ); + _POSIX_signals_Clear_process_signals( signo ); + /* + * It may be impossible to get here with an empty chain + * BUT until that is proven we need to be defensive and + * protect against it. + */ + if ( psiginfo ) { + *info = psiginfo->Info; + _Chain_Append_unprotected( + &_POSIX_signals_Inactive_siginfo, + &psiginfo->Node + ); + } else + do_callout = false; + } + _POSIX_signals_Clear_process_signals( signo ); + do_callout = true; + } + } else { + if ( mask & (api->signals_pending & signals_blocked) ) { + api->signals_pending &= ~mask; + do_callout = true; + } + } + _ISR_Enable( level ); + return do_callout; +} diff --git a/cpukit/posix/src/psignalsetprocesssignals.c b/cpukit/posix/src/psignalsetprocesssignals.c new file mode 100644 index 0000000000..cb4ad8b241 --- /dev/null +++ b/cpukit/posix/src/psignalsetprocesssignals.c @@ -0,0 +1,46 @@ +/* + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <errno.h> +#include <pthread.h> +#include <signal.h> + +#include <rtems/system.h> +#include <rtems/score/isr.h> +#include <rtems/score/thread.h> +#include <rtems/score/tqdata.h> +#include <rtems/score/wkspace.h> +#include <rtems/seterr.h> +#include <rtems/posix/threadsup.h> +#include <rtems/posix/psignal.h> +#include <rtems/posix/pthread.h> +#include <rtems/posix/time.h> +#include <stdio.h> + +/*PAGE + * + * _POSIX_signals_Set_process_signals + */ + +void _POSIX_signals_Set_process_signals( + sigset_t mask +) +{ + ISR_Level level; + + _ISR_Disable( level ); + _POSIX_signals_Pending |= mask; + _ISR_Enable( level ); +} diff --git a/cpukit/posix/src/psignalunblockthread.c b/cpukit/posix/src/psignalunblockthread.c new file mode 100644 index 0000000000..f6bf5fcc7d --- /dev/null +++ b/cpukit/posix/src/psignalunblockthread.c @@ -0,0 +1,120 @@ +/* + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <errno.h> +#include <pthread.h> +#include <signal.h> + +#include <rtems/system.h> +#include <rtems/score/isr.h> +#include <rtems/score/thread.h> +#include <rtems/score/tqdata.h> +#include <rtems/score/wkspace.h> +#include <rtems/seterr.h> +#include <rtems/posix/threadsup.h> +#include <rtems/posix/psignal.h> +#include <rtems/posix/pthread.h> +#include <rtems/posix/time.h> +#include <stdio.h> + + +/*PAGE + * + * _POSIX_signals_Unblock_thread + */ + +/* XXX this routine could probably be cleaned up */ +bool _POSIX_signals_Unblock_thread( + Thread_Control *the_thread, + int signo, + siginfo_t *info +) +{ + POSIX_API_Control *api; + sigset_t mask; + siginfo_t *the_info = NULL; + + api = the_thread->API_Extensions[ THREAD_API_POSIX ]; + + mask = signo_to_mask( signo ); + + /* + * Is the thread is specifically waiting for a signal? + */ + + if ( _States_Is_interruptible_signal( the_thread->current_state ) ) { + + if ( (the_thread->Wait.option & mask) || (~api->signals_blocked & mask) ) { + the_thread->Wait.return_code = EINTR; + + the_info = (siginfo_t *) the_thread->Wait.return_argument; + + if ( !info ) { + the_info->si_signo = signo; + the_info->si_code = SI_USER; + the_info->si_value.sival_int = 0; + } else { + *the_info = *info; + } + + _Thread_queue_Extract_with_proxy( the_thread ); + return true; + } + + /* + * This should only be reached via pthread_kill(). + */ + + return false; + } + + /* + * Thread is not waiting due to a sigwait. + */ + if ( ~api->signals_blocked & mask ) { + + /* + * The thread is interested in this signal. We are going + * to post it. We have a few broad cases: + * + If it is blocked on an interruptible signal, THEN + * we unblock the thread. + * + If it is in the ready state AND + * we are sending from an ISR AND + * it is the interrupted thread AND + * it is not blocked, THEN + * we need to dispatch at the end of this ISR. + * + Any other combination, do nothing. + */ + + if ( _States_Is_interruptible_by_signal( the_thread->current_state ) ) { + the_thread->Wait.return_code = EINTR; + /* + * In pthread_cond_wait, a thread will be blocking on a thread + * queue, but is also interruptible by a POSIX signal. + */ + if ( _States_Is_waiting_on_thread_queue(the_thread->current_state) ) + _Thread_queue_Extract_with_proxy( the_thread ); + else if ( _States_Is_delaying(the_thread->current_state) ) { + (void) _Watchdog_Remove( &the_thread->Timer ); + _Thread_Unblock( the_thread ); + } + + } else if ( the_thread->current_state == STATES_READY ) { + if ( _ISR_Is_in_progress() && _Thread_Is_executing( the_thread ) ) + _Thread_Dispatch_necessary = true; + } + } + return false; +} diff --git a/cpukit/posix/src/pspin.c b/cpukit/posix/src/pspin.c new file mode 100644 index 0000000000..88dadf2cba --- /dev/null +++ b/cpukit/posix/src/pspin.c @@ -0,0 +1,57 @@ +/* + * Spinlock Manager + * + * DESCRIPTION: + * + * This package is the implementation of the Spinlock Manager. + * + * Directives provided are: + * + * + create a spinlock + * + get an ID of a spinlock + * + delete a spinlock + * + acquire a spinlock + * + release a spinlock + * + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <limits.h> + +#include <rtems/system.h> +#include <rtems/config.h> +#include <rtems/posix/spinlock.h> + +/** + * @brief _POSIX_Spinlock_Manager_initialization + */ + +void _POSIX_Spinlock_Manager_initialization(void) +{ + _Objects_Initialize_information( + &_POSIX_Spinlock_Information, /* object information table */ + OBJECTS_POSIX_API, /* object API */ + OBJECTS_POSIX_SPINLOCKS, /* object class */ + Configuration_POSIX_API.maximum_spinlocks, + /* maximum objects of this class */ + sizeof( POSIX_Spinlock_Control ),/* size of this object's control block */ + true, /* true if the name is a string */ + _POSIX_PATH_MAX /* maximum length of each object's name */ +#if defined(RTEMS_MULTIPROCESSING) + , + false, /* true if this is a global object class */ + NULL /* Proxy extraction support callout */ +#endif + ); +} diff --git a/cpukit/posix/src/pspindestroy.c b/cpukit/posix/src/pspindestroy.c new file mode 100644 index 0000000000..aa3c465ec7 --- /dev/null +++ b/cpukit/posix/src/pspindestroy.c @@ -0,0 +1,73 @@ +/* + * POSIX Spinlock Manager -- Destroy a Spinlock + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/spinlock.h> + +/* + * pthread_spin_destroy + * + * This directive allows a thread to delete a spinlock specified by + * the spinlock id. The spinlock is freed back to the inactive + * spinlock chain. + * + * Input parameters: + * spinlock - spinlock id + * + * Output parameters: + * 0 - if successful + * error code - if unsuccessful + */ + +int pthread_spin_destroy( + pthread_spinlock_t *spinlock +) +{ + POSIX_Spinlock_Control *the_spinlock = NULL; + Objects_Locations location; + + if ( !spinlock ) + return EINVAL; + + the_spinlock = _POSIX_Spinlock_Get( spinlock, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + if ( _CORE_spinlock_Is_busy( &the_spinlock->Spinlock ) ) { + _Thread_Enable_dispatch(); + return EBUSY; + } + + _Objects_Close( &_POSIX_Spinlock_Information, &the_spinlock->Object ); + + _POSIX_Spinlock_Free( the_spinlock ); + + _Thread_Enable_dispatch(); + return 0; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: +#endif + case OBJECTS_ERROR: + break; + } + + return EINVAL; +} diff --git a/cpukit/posix/src/pspininit.c b/cpukit/posix/src/pspininit.c new file mode 100644 index 0000000000..bab6ac3140 --- /dev/null +++ b/cpukit/posix/src/pspininit.c @@ -0,0 +1,78 @@ +/* + * POSIX Spinlock Manager -- Initialize a Spinlock Instance + * + * COPYRIGHT (c) 1989-2006. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/spinlock.h> + +/* + * pthread_spinlock_init + * + * This directive creates a spinlock. A spinlock id is returned. + * + * Input parameters: + * spinlock - pointer to spinlock id + * pshared - is this spinlock shared between processes + * + * Output parameters: + * spinlock - spinlock id + * 0 - if successful + * error code - if unsuccessful + */ + +int pthread_spin_init( + pthread_spinlock_t *spinlock, + int pshared +) +{ + POSIX_Spinlock_Control *the_spinlock; + CORE_spinlock_Attributes attributes; + + + if ( !spinlock ) + return EINVAL; + + switch ( pshared ) { + case PTHREAD_PROCESS_PRIVATE: /* only supported values */ + break; + case PTHREAD_PROCESS_SHARED: + default: + return EINVAL; + } + + _Thread_Disable_dispatch(); /* prevents deletion */ + + the_spinlock = _POSIX_Spinlock_Allocate(); + + if ( !the_spinlock ) { + _Thread_Enable_dispatch(); + return EAGAIN; + } + + _CORE_spinlock_Initialize_attributes( &attributes ); + + _CORE_spinlock_Initialize( &the_spinlock->Spinlock, &attributes ); + + _Objects_Open_u32( &_POSIX_Spinlock_Information, &the_spinlock->Object, 0 ); + + *spinlock = the_spinlock->Object.id; + + _Thread_Enable_dispatch(); + return 0; +} diff --git a/cpukit/posix/src/pspinlock.c b/cpukit/posix/src/pspinlock.c new file mode 100644 index 0000000000..845117a3e3 --- /dev/null +++ b/cpukit/posix/src/pspinlock.c @@ -0,0 +1,64 @@ +/* + * POSIX Spinlock Manager -- Wait at a Spinlock + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/spinlock.h> + +/* + * pthread_spin_lock + * + * This directive allows a thread to wait at a spinlock. + * + * Input parameters: + * spinlock - spinlock id + * + * Output parameters: + * 0 - if successful + * error code - if unsuccessful + */ + +int pthread_spin_lock( + pthread_spinlock_t *spinlock +) +{ + POSIX_Spinlock_Control *the_spinlock = NULL; + Objects_Locations location; + CORE_spinlock_Status status; + + if ( !spinlock ) + return EINVAL; + + the_spinlock = _POSIX_Spinlock_Get( spinlock, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + status = _CORE_spinlock_Wait( &the_spinlock->Spinlock, true, 0 ); + _Thread_Enable_dispatch(); + return _POSIX_Spinlock_Translate_core_spinlock_return_code( status ); + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: +#endif + case OBJECTS_ERROR: + break; + } + + return EINVAL; +} diff --git a/cpukit/posix/src/pspinlocktranslatereturncode.c b/cpukit/posix/src/pspinlocktranslatereturncode.c new file mode 100644 index 0000000000..fbce440010 --- /dev/null +++ b/cpukit/posix/src/pspinlocktranslatereturncode.c @@ -0,0 +1,58 @@ +/* + * Spinlock Manager -- Translate SuperCore Status + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/score/corespinlock.h> + +/* + * _POSIX_Spinlock_Translate_core_spinlock_return_code + * + * Input parameters: + * the_spinlock_status - spinlock status code to translate + * + * Output parameters: + * status code - translated POSIX status code + * + */ + +static int _POSIX_Spinlock_Return_codes[CORE_SPINLOCK_STATUS_LAST + 1] = { + 0, /* CORE_SPINLOCK_SUCCESSFUL */ + EDEADLK, /* CORE_SPINLOCK_HOLDER_RELOCKING */ + EPERM, /* CORE_SPINLOCK_NOT_HOLDER */ + -1, /* CORE_SPINLOCK_TIMEOUT */ + EBUSY, /* CORE_SPINLOCK_IS_BUSY */ + EBUSY, /* CORE_SPINLOCK_UNAVAILABLE */ + 0 /* CORE_SPINLOCK_NOT_LOCKED */ +}; + + +int _POSIX_Spinlock_Translate_core_spinlock_return_code( + CORE_spinlock_Status the_spinlock_status +) +{ + /* + * Internal consistency check for bad status from SuperCore + */ + #if defined(RTEMS_DEBUG) + if ( the_spinlock_status > CORE_SPINLOCK_STATUS_LAST ) + return EINVAL; + #endif + return _POSIX_Spinlock_Return_codes[the_spinlock_status]; +} diff --git a/cpukit/posix/src/pspintrylock.c b/cpukit/posix/src/pspintrylock.c new file mode 100644 index 0000000000..7e66d88e8b --- /dev/null +++ b/cpukit/posix/src/pspintrylock.c @@ -0,0 +1,64 @@ +/* + * POSIX Spinlock Manager -- Wait at a Spinlock + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/spinlock.h> + +/* + * pthread_spin_trylock + * + * This directive allows a thread to poll an attempt at locking a spinlock. + * + * Input parameters: + * spinlock - spinlock id + * + * Output parameters: + * 0 - if successful + * error code - if unsuccessful + */ + +int pthread_spin_trylock( + pthread_spinlock_t *spinlock +) +{ + POSIX_Spinlock_Control *the_spinlock = NULL; + Objects_Locations location; + CORE_spinlock_Status status; + + if ( !spinlock ) + return EINVAL; + + the_spinlock = _POSIX_Spinlock_Get( spinlock, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + status = _CORE_spinlock_Wait( &the_spinlock->Spinlock, false, 0 ); + _Thread_Enable_dispatch(); + return _POSIX_Spinlock_Translate_core_spinlock_return_code( status ); + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: +#endif + case OBJECTS_ERROR: + break; + } + + return EINVAL; +} diff --git a/cpukit/posix/src/pspinunlock.c b/cpukit/posix/src/pspinunlock.c new file mode 100644 index 0000000000..8bbf4f2f61 --- /dev/null +++ b/cpukit/posix/src/pspinunlock.c @@ -0,0 +1,64 @@ +/* + * POSIX Spinlock Manager -- Wait at a Spinlock + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/spinlock.h> + +/* + * pthread_spin_unlock + * + * This directive allows a thread to wait at a spinlock. + * + * Input parameters: + * spinlock - spinlock id + * + * Output parameters: + * 0 - if successful + * error code - if unsuccessful + */ + +int pthread_spin_unlock( + pthread_spinlock_t *spinlock +) +{ + POSIX_Spinlock_Control *the_spinlock = NULL; + Objects_Locations location; + CORE_spinlock_Status status; + + if ( !spinlock ) + return EINVAL; + + the_spinlock = _POSIX_Spinlock_Get( spinlock, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + status = _CORE_spinlock_Release( &the_spinlock->Spinlock ); + _Thread_Enable_dispatch(); + return _POSIX_Spinlock_Translate_core_spinlock_return_code( status ); + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: +#endif + case OBJECTS_ERROR: + break; + } + + return EINVAL; +} diff --git a/cpukit/posix/src/psxpriorityisvalid.c b/cpukit/posix/src/psxpriorityisvalid.c new file mode 100644 index 0000000000..4b35a81e62 --- /dev/null +++ b/cpukit/posix/src/psxpriorityisvalid.c @@ -0,0 +1,27 @@ +/* + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/system.h> +#include <rtems/posix/priority.h> + +bool _POSIX_Priority_Is_valid( + int priority +) +{ + return ((priority >= POSIX_SCHEDULER_MINIMUM_PRIORITY) && + (priority <= POSIX_SCHEDULER_MAXIMUM_PRIORITY)); + +} + diff --git a/cpukit/posix/src/psxtransschedparam.c b/cpukit/posix/src/psxtransschedparam.c new file mode 100644 index 0000000000..7be4dcc641 --- /dev/null +++ b/cpukit/posix/src/psxtransschedparam.c @@ -0,0 +1,73 @@ +/* COPYRIGHT (c) 1989-2009. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/pthread.h> +#include <rtems/posix/priority.h> +#include <rtems/posix/time.h> + +int _POSIX_Thread_Translate_sched_param( + int policy, + struct sched_param *param, + Thread_CPU_budget_algorithms *budget_algorithm, + Thread_CPU_budget_algorithm_callout *budget_callout +) +{ + if ( !_POSIX_Priority_Is_valid( param->sched_priority ) ) + return EINVAL; + + *budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_NONE; + *budget_callout = NULL; + + if ( policy == SCHED_OTHER ) { + *budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE; + return 0; + } + + if ( policy == SCHED_FIFO ) { + *budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_NONE; + return 0; + } + + if ( policy == SCHED_RR ) { + *budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_EXHAUST_TIMESLICE; + return 0; + } + + if ( policy == SCHED_SPORADIC ) { + if ( (param->sched_ss_repl_period.tv_sec == 0) && + (param->sched_ss_repl_period.tv_nsec == 0) ) + return EINVAL; + + if ( (param->sched_ss_init_budget.tv_sec == 0) && + (param->sched_ss_init_budget.tv_nsec == 0) ) + return EINVAL; + + if ( _Timespec_To_ticks( ¶m->sched_ss_repl_period ) < + _Timespec_To_ticks( ¶m->sched_ss_init_budget ) ) + return EINVAL; + + if ( !_POSIX_Priority_Is_valid( param->sched_ss_low_priority ) ) + return EINVAL; + + *budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_CALLOUT; + *budget_callout = _POSIX_Threads_Sporadic_budget_callout; + return 0; + } + + return EINVAL; +} diff --git a/cpukit/posix/src/pthread.c b/cpukit/posix/src/pthread.c new file mode 100644 index 0000000000..3890144aa5 --- /dev/null +++ b/cpukit/posix/src/pthread.c @@ -0,0 +1,366 @@ +/* + * COPYRIGHT (c) 1989-2010. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <errno.h> +#include <pthread.h> +#include <limits.h> + +#include <rtems/system.h> +#include <rtems/config.h> +#include <rtems/score/apiext.h> +#include <rtems/score/stack.h> +#include <rtems/score/thread.h> +#include <rtems/score/userext.h> +#include <rtems/score/wkspace.h> +#include <rtems/posix/cancel.h> +#include <rtems/posix/pthread.h> +#include <rtems/posix/priority.h> +#include <rtems/posix/psignal.h> +#include <rtems/posix/config.h> +#include <rtems/posix/key.h> +#include <rtems/posix/time.h> +#include <rtems/score/timespec.h> + +/* + * The default pthreads attributes structure. + * + * NOTE: Be careful .. if the default attribute set changes, + * _POSIX_Threads_Initialize_user_threads will need to be examined. + */ +const pthread_attr_t _POSIX_Threads_Default_attributes = { + true, /* is_initialized */ + NULL, /* stackaddr */ + 0, /* stacksize -- will be adjusted to minimum */ + PTHREAD_SCOPE_PROCESS, /* contentionscope */ + PTHREAD_INHERIT_SCHED, /* inheritsched */ + SCHED_FIFO, /* schedpolicy */ + { /* schedparam */ + 2, /* sched_priority */ + #if defined(_POSIX_SPORADIC_SERVER) || \ + defined(_POSIX_THREAD_SPORADIC_SERVER) + 0, /* sched_ss_low_priority */ + { 0L, 0 }, /* sched_ss_repl_period */ + { 0L, 0 } /* sched_ss_init_budget */ + #endif + }, + #if HAVE_DECL_PTHREAD_ATTR_SETGUARDSIZE + 0, /* guardsize */ + #endif + #if defined(_POSIX_THREAD_CPUTIME) + 1, /* cputime_clock_allowed */ + #endif + PTHREAD_CREATE_JOINABLE, /* detachstate */ +}; + +/* + * _POSIX_Threads_Sporadic_budget_TSR + */ +void _POSIX_Threads_Sporadic_budget_TSR( + Objects_Id id __attribute__((unused)), + void *argument +) +{ + uint32_t ticks; + uint32_t new_priority; + Thread_Control *the_thread; + POSIX_API_Control *api; + + the_thread = argument; + + api = the_thread->API_Extensions[ THREAD_API_POSIX ]; + + /* ticks is guaranteed to be at least one */ + ticks = _Timespec_To_ticks( &api->schedparam.sched_ss_init_budget ); + + the_thread->cpu_time_budget = ticks; + + new_priority = _POSIX_Priority_To_core( api->schedparam.sched_priority ); + the_thread->real_priority = new_priority; + + /* + * If holding a resource, then do not change it. + */ + #if 0 + printk( "TSR %d %d %d\n", the_thread->resource_count, + the_thread->current_priority, new_priority ); + #endif + if ( the_thread->resource_count == 0 ) { + /* + * If this would make them less important, then do not change it. + */ + if ( the_thread->current_priority > new_priority ) { + _Thread_Change_priority( the_thread, new_priority, true ); + #if 0 + printk( "raise priority\n" ); + #endif + } + } + + /* ticks is guaranteed to be at least one */ + ticks = _Timespec_To_ticks( &api->schedparam.sched_ss_repl_period ); + + _Watchdog_Insert_ticks( &api->Sporadic_timer, ticks ); +} + +/* + * _POSIX_Threads_Sporadic_budget_callout + */ +void _POSIX_Threads_Sporadic_budget_callout( + Thread_Control *the_thread +) +{ + POSIX_API_Control *api; + uint32_t new_priority; + + api = the_thread->API_Extensions[ THREAD_API_POSIX ]; + + /* + * This will prevent the thread from consuming its entire "budget" + * while at low priority. + */ + the_thread->cpu_time_budget = 0xFFFFFFFF; /* XXX should be based on MAX_U32 */ + + new_priority = _POSIX_Priority_To_core(api->schedparam.sched_ss_low_priority); + the_thread->real_priority = new_priority; + + /* + * If holding a resource, then do not change it. + */ + #if 0 + printk( "callout %d %d %d\n", the_thread->resource_count, + the_thread->current_priority, new_priority ); + #endif + if ( the_thread->resource_count == 0 ) { + /* + * Make sure we are actually lowering it. If they have lowered it + * to logically lower than sched_ss_low_priority, then we do not want to + * change it. + */ + if ( the_thread->current_priority < new_priority ) { + _Thread_Change_priority( the_thread, new_priority, true ); + #if 0 + printk( "lower priority\n" ); + #endif + } + } +} + +/* + * _POSIX_Threads_Create_extension + * + * This method is invoked for each thread created. + */ + +bool _POSIX_Threads_Create_extension( + Thread_Control *executing __attribute__((unused)), + Thread_Control *created +) +{ + POSIX_API_Control *api; + POSIX_API_Control *executing_api; + + api = _Workspace_Allocate( sizeof( POSIX_API_Control ) ); + + if ( !api ) + return false; + + created->API_Extensions[ THREAD_API_POSIX ] = api; + + /* XXX check all fields are touched */ + api->Attributes = _POSIX_Threads_Default_attributes; + api->detachstate = _POSIX_Threads_Default_attributes.detachstate; + api->schedpolicy = _POSIX_Threads_Default_attributes.schedpolicy; + api->schedparam = _POSIX_Threads_Default_attributes.schedparam; + api->schedparam.sched_priority = + _POSIX_Priority_From_core( created->current_priority ); + + /* + * POSIX 1003.1 1996, 18.2.2.2 + */ + api->cancelation_requested = 0; + api->cancelability_state = PTHREAD_CANCEL_ENABLE; + api->cancelability_type = PTHREAD_CANCEL_DEFERRED; + _Chain_Initialize_empty (&api->Cancellation_Handlers); + + /* + * If the thread is not a posix thread, then all posix signals are blocked + * by default. + * + * The check for class == 1 is debug. Should never really happen. + */ + + /* XXX use signal constants */ + api->signals_pending = 0; + if ( _Objects_Get_API( created->Object.id ) == OBJECTS_POSIX_API + #if defined(RTEMS_DEBUG) + && _Objects_Get_class( created->Object.id ) == 1 + #endif + ) { + executing_api = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ]; + api->signals_blocked = executing_api->signals_blocked; + } else { + api->signals_blocked = 0xffffffff; + } + + _Thread_queue_Initialize( + &api->Join_List, + THREAD_QUEUE_DISCIPLINE_FIFO, + STATES_WAITING_FOR_JOIN_AT_EXIT, + 0 + ); + + _Watchdog_Initialize( + &api->Sporadic_timer, + _POSIX_Threads_Sporadic_budget_TSR, + created->Object.id, + created + ); + + return true; +} + +/* + * _POSIX_Threads_Delete_extension + * + * This method is invoked for each thread deleted. + */ +void _POSIX_Threads_Delete_extension( + Thread_Control *executing __attribute__((unused)), + Thread_Control *deleted +) +{ + Thread_Control *the_thread; + POSIX_API_Control *api; + void **value_ptr; + + api = deleted->API_Extensions[ THREAD_API_POSIX ]; + + /* + * Run the POSIX cancellation handlers + */ + _POSIX_Threads_cancel_run( deleted ); + + /* + * Run all the key destructors + */ + _POSIX_Keys_Run_destructors( deleted ); + + /* + * Wakeup all the tasks which joined with this one + */ + value_ptr = (void **) deleted->Wait.return_argument; + + while ( (the_thread = _Thread_queue_Dequeue( &api->Join_List )) ) + *(void **)the_thread->Wait.return_argument = value_ptr; + + if ( api->schedpolicy == SCHED_SPORADIC ) + (void) _Watchdog_Remove( &api->Sporadic_timer ); + + deleted->API_Extensions[ THREAD_API_POSIX ] = NULL; + + _Workspace_Free( api ); +} + +/* + * _POSIX_Threads_Exitted_extension + * + * This method is invoked each time a thread exits. + */ +void _POSIX_Threads_Exitted_extension( + Thread_Control *executing +) +{ + /* + * If the executing thread was not created with the POSIX API, then this + * API do not get to define its exit behavior. + */ + if ( _Objects_Get_API( executing->Object.id ) == OBJECTS_POSIX_API ) + pthread_exit( executing->Wait.return_argument ); +} + +/* + * _POSIX_Threads_Initialize_user_threads + * + * This routine creates and starts all configured user + * initialzation threads. + */ +void _POSIX_Threads_Initialize_user_threads( void ) +{ + if ( _POSIX_Threads_Initialize_user_threads_p ) + (*_POSIX_Threads_Initialize_user_threads_p)(); +} + +/* + * API Extension control structures + */ +API_extensions_Control _POSIX_Threads_API_extensions = { + { NULL, NULL }, + #if defined(FUNCTIONALITY_NOT_CURRENTLY_USED_BY_ANY_API) + NULL, /* predriver */ + #endif + _POSIX_Threads_Initialize_user_threads, /* postdriver */ + _POSIX_signals_Post_switch_extension, /* post switch */ +}; + +User_extensions_Control _POSIX_Threads_User_extensions = { + { NULL, NULL }, + { { NULL, NULL }, NULL }, + { _POSIX_Threads_Create_extension, /* create */ + NULL, /* start */ + NULL, /* restart */ + _POSIX_Threads_Delete_extension, /* delete */ + NULL, /* switch */ + NULL, /* begin */ + _POSIX_Threads_Exitted_extension, /* exitted */ + NULL /* fatal */ + } +}; + +/* + * _POSIX_Threads_Manager_initialization + * + * This routine initializes all threads manager related data structures. + */ +void _POSIX_Threads_Manager_initialization(void) +{ + _Objects_Initialize_information( + &_POSIX_Threads_Information, /* object information table */ + OBJECTS_POSIX_API, /* object API */ + OBJECTS_POSIX_THREADS, /* object class */ + Configuration_POSIX_API.maximum_threads, + /* maximum objects of this class */ + sizeof( Thread_Control ), + /* size of this object's control block */ + true, /* true if names for this object are strings */ + _POSIX_PATH_MAX /* maximum length of each object's name */ +#if defined(RTEMS_MULTIPROCESSING) + , + false, /* true if this is a global object class */ + NULL /* Proxy extraction support callout */ +#endif + ); + + /* + * Add all the extensions for this API + */ + _User_extensions_Add_API_set( &_POSIX_Threads_User_extensions ); + + _API_extensions_Add( &_POSIX_Threads_API_extensions ); + + /* + * If we supported MP, then here we would ... + * Register the MP Process Packet routine. + */ +} diff --git a/cpukit/posix/src/pthreadatfork.c b/cpukit/posix/src/pthreadatfork.c new file mode 100644 index 0000000000..9a08abd254 --- /dev/null +++ b/cpukit/posix/src/pthreadatfork.c @@ -0,0 +1,37 @@ +/* + * pthread_atfork() - POSIX 1003.1b 3.1.3 + * + * 3.1.3 Register Fork Handlers, P1003.1c/Draft 10, P1003.1c/Draft 10, p. 27 + * + * RTEMS does not support processes, so we fall under this and do not + * provide this routine: + * + * "Either the implementation shall support the pthread_atfork() function + * as described above or the pthread_atfork() funciton shall not be + * provided." + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <errno.h> +#include <rtems/seterr.h> + +int pthread_atfork( + void (*prepare)(void) __attribute__((unused)), + void (*parent)(void) __attribute__((unused)), + void (*child)(void) __attribute__((unused)) +) +{ + rtems_set_errno_and_return_minus_one( ENOSYS ); +} diff --git a/cpukit/posix/src/pthreadattrdestroy.c b/cpukit/posix/src/pthreadattrdestroy.c new file mode 100644 index 0000000000..60787322e7 --- /dev/null +++ b/cpukit/posix/src/pthreadattrdestroy.c @@ -0,0 +1,32 @@ +/* + * 16.1.1 Thread Creation Attributes, P1003.1c/Draft 10, p, 140 + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> + +int pthread_attr_destroy( + pthread_attr_t *attr +) +{ + if ( !attr || !attr->is_initialized ) + return EINVAL; + + attr->is_initialized = false; + return 0; +} diff --git a/cpukit/posix/src/pthreadattrgetdetachstate.c b/cpukit/posix/src/pthreadattrgetdetachstate.c new file mode 100644 index 0000000000..bd8b9a02ae --- /dev/null +++ b/cpukit/posix/src/pthreadattrgetdetachstate.c @@ -0,0 +1,31 @@ +/* + * 16.1.1 Thread Creation Attributes, P1003.1c/Draft 10, p, 140 + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +int pthread_attr_getdetachstate( + const pthread_attr_t *attr, + int *detachstate +) +{ + if ( !attr || !attr->is_initialized || !detachstate ) + return EINVAL; + + *detachstate = attr->detachstate; + return 0; +} diff --git a/cpukit/posix/src/pthreadattrgetguardsize.c b/cpukit/posix/src/pthreadattrgetguardsize.c new file mode 100644 index 0000000000..b3c64fbfad --- /dev/null +++ b/cpukit/posix/src/pthreadattrgetguardsize.c @@ -0,0 +1,33 @@ +/* + * 16.1.1 Thread Creation Attributes + * + * COPYRIGHT (c) 1989-2010. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#if HAVE_DECL_PTHREAD_ATTR_GETGUARDSIZE +#include <pthread.h> +#include <errno.h> + +int pthread_attr_getguardsize( + const pthread_attr_t *attr, + size_t *guardsize +) +{ + if ( !attr || !attr->is_initialized || !guardsize ) + return EINVAL; + + *guardsize = attr->guardsize; + return 0; +} +#endif diff --git a/cpukit/posix/src/pthreadattrgetinheritsched.c b/cpukit/posix/src/pthreadattrgetinheritsched.c new file mode 100644 index 0000000000..e924f2d26c --- /dev/null +++ b/cpukit/posix/src/pthreadattrgetinheritsched.c @@ -0,0 +1,31 @@ +/* + * 13.5.1 Thread Creation Scheduling Attributes, P1003.1c/Draft 10, p. 120 + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +int pthread_attr_getinheritsched( + const pthread_attr_t *attr, + int *inheritsched +) +{ + if ( !attr || !attr->is_initialized || !inheritsched ) + return EINVAL; + + *inheritsched = attr->inheritsched; + return 0; +} diff --git a/cpukit/posix/src/pthreadattrgetschedparam.c b/cpukit/posix/src/pthreadattrgetschedparam.c new file mode 100644 index 0000000000..2ec95d729e --- /dev/null +++ b/cpukit/posix/src/pthreadattrgetschedparam.c @@ -0,0 +1,31 @@ +/* + * 13.5.1 Thread Creation Scheduling Attributes, P1003.1c/Draft 10, p. 120 + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +int pthread_attr_getschedparam( + const pthread_attr_t *attr, + struct sched_param *param +) +{ + if ( !attr || !attr->is_initialized || !param ) + return EINVAL; + + *param = attr->schedparam; + return 0; +} diff --git a/cpukit/posix/src/pthreadattrgetschedpolicy.c b/cpukit/posix/src/pthreadattrgetschedpolicy.c new file mode 100644 index 0000000000..571430e953 --- /dev/null +++ b/cpukit/posix/src/pthreadattrgetschedpolicy.c @@ -0,0 +1,31 @@ +/* + * 13.5.1 Thread Creation Scheduling Parameters, P1003.1c/Draft 10, p. 120 + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +int pthread_attr_getschedpolicy( + const pthread_attr_t *attr, + int *policy +) +{ + if ( !attr || !attr->is_initialized || !policy ) + return EINVAL; + + *policy = attr->schedpolicy; + return 0; +} diff --git a/cpukit/posix/src/pthreadattrgetscope.c b/cpukit/posix/src/pthreadattrgetscope.c new file mode 100644 index 0000000000..2d74dc30ba --- /dev/null +++ b/cpukit/posix/src/pthreadattrgetscope.c @@ -0,0 +1,31 @@ +/* + * 13.5.1 Thread Creation Scheduling Attributes, P1003.1c/Draft 10, p. 120 + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +int pthread_attr_getscope( + const pthread_attr_t *attr, + int *contentionscope +) +{ + if ( !attr || !attr->is_initialized || !contentionscope ) + return EINVAL; + + *contentionscope = attr->contentionscope; + return 0; +} diff --git a/cpukit/posix/src/pthreadattrgetstack.c b/cpukit/posix/src/pthreadattrgetstack.c new file mode 100644 index 0000000000..8303099a96 --- /dev/null +++ b/cpukit/posix/src/pthreadattrgetstack.c @@ -0,0 +1,35 @@ +/* + * 16.1.1 Thread Creation Attributes + * + * COPYRIGHT (c) 1989-2010. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#if HAVE_DECL_PTHREAD_ATTR_GETSTACK +#include <pthread.h> +#include <errno.h> + +int pthread_attr_getstack( + const pthread_attr_t *attr, + void **stackaddr, + size_t *stacksize +) +{ + if ( !attr || !attr->is_initialized || !stackaddr || !stacksize ) + return EINVAL; + + *stackaddr = attr->stackaddr; + *stacksize = attr->stacksize; + return 0; +} +#endif diff --git a/cpukit/posix/src/pthreadattrgetstackaddr.c b/cpukit/posix/src/pthreadattrgetstackaddr.c new file mode 100644 index 0000000000..3ca66112aa --- /dev/null +++ b/cpukit/posix/src/pthreadattrgetstackaddr.c @@ -0,0 +1,31 @@ +/* + * 16.1.1 Thread Creation Attributes, P1003.1c/Draft 10, p, 140 + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +int pthread_attr_getstackaddr( + const pthread_attr_t *attr, + void **stackaddr +) +{ + if ( !attr || !attr->is_initialized || !stackaddr ) + return EINVAL; + + *stackaddr = attr->stackaddr; + return 0; +} diff --git a/cpukit/posix/src/pthreadattrgetstacksize.c b/cpukit/posix/src/pthreadattrgetstacksize.c new file mode 100644 index 0000000000..f7f23c6dd6 --- /dev/null +++ b/cpukit/posix/src/pthreadattrgetstacksize.c @@ -0,0 +1,31 @@ +/* + * 16.1.1 Thread Creation Attributes, P1003.1c/Draft 10, p, 140 + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +int pthread_attr_getstacksize( + const pthread_attr_t *attr, + size_t *stacksize +) +{ + if ( !attr || !attr->is_initialized || !stacksize ) + return EINVAL; + + *stacksize = attr->stacksize; + return 0; +} diff --git a/cpukit/posix/src/pthreadattrinit.c b/cpukit/posix/src/pthreadattrinit.c new file mode 100644 index 0000000000..1862623e3e --- /dev/null +++ b/cpukit/posix/src/pthreadattrinit.c @@ -0,0 +1,33 @@ +/* + * 16.1.1 Thread Creation Attributes, P1003.1c/Draft 10, p, 140 + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/pthread.h> + +int pthread_attr_init( + pthread_attr_t *attr +) +{ + if ( !attr ) + return EINVAL; + + *attr = _POSIX_Threads_Default_attributes; + return 0; +} diff --git a/cpukit/posix/src/pthreadattrsetdetachstate.c b/cpukit/posix/src/pthreadattrsetdetachstate.c new file mode 100644 index 0000000000..cb29f44d3a --- /dev/null +++ b/cpukit/posix/src/pthreadattrsetdetachstate.c @@ -0,0 +1,38 @@ +/* + * 16.1.1 Thread Creation Attributes, P1003.1c/Draft 10, p, 140 + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +int pthread_attr_setdetachstate( + pthread_attr_t *attr, + int detachstate +) +{ + if ( !attr || !attr->is_initialized ) + return EINVAL; + + switch ( detachstate ) { + case PTHREAD_CREATE_DETACHED: + case PTHREAD_CREATE_JOINABLE: + attr->detachstate = detachstate; + return 0; + + default: + return EINVAL; + } +} diff --git a/cpukit/posix/src/pthreadattrsetguardsize.c b/cpukit/posix/src/pthreadattrsetguardsize.c new file mode 100644 index 0000000000..f69ff7b173 --- /dev/null +++ b/cpukit/posix/src/pthreadattrsetguardsize.c @@ -0,0 +1,36 @@ +/* + * 16.1.1 Thread Creation Attributes + * + * COPYRIGHT (c) 1989-2010. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#if HAVE_DECL_PTHREAD_ATTR_SETGUARDSIZE +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/pthread.h> + +int pthread_attr_setguardsize( + pthread_attr_t *attr, + size_t guardsize +) +{ + if ( !attr || !attr->is_initialized ) + return EINVAL; + + attr->guardsize = guardsize; + return 0; +} +#endif diff --git a/cpukit/posix/src/pthreadattrsetinheritsched.c b/cpukit/posix/src/pthreadattrsetinheritsched.c new file mode 100644 index 0000000000..0819eb48b7 --- /dev/null +++ b/cpukit/posix/src/pthreadattrsetinheritsched.c @@ -0,0 +1,41 @@ +/* + * 13.5.1 Thread Creation Scheduling Attributes, P1003.1c/Draft 10, p. 120 + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/pthread.h> + +int pthread_attr_setinheritsched( + pthread_attr_t *attr, + int inheritsched +) +{ + if ( !attr || !attr->is_initialized ) + return EINVAL; + + switch ( inheritsched ) { + case PTHREAD_INHERIT_SCHED: + case PTHREAD_EXPLICIT_SCHED: + attr->inheritsched = inheritsched; + return 0; + + default: + return ENOTSUP; + } +} diff --git a/cpukit/posix/src/pthreadattrsetschedparam.c b/cpukit/posix/src/pthreadattrsetschedparam.c new file mode 100644 index 0000000000..cb310a9893 --- /dev/null +++ b/cpukit/posix/src/pthreadattrsetschedparam.c @@ -0,0 +1,31 @@ +/* + * 13.5.1 Thread Creation Scheduling Parameters, P1003.1c/Draft 10, p. 120 + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +int pthread_attr_setschedparam( + pthread_attr_t *attr, + const struct sched_param *param +) +{ + if ( !attr || !attr->is_initialized || !param ) + return EINVAL; + + attr->schedparam = *param; + return 0; +} diff --git a/cpukit/posix/src/pthreadattrsetschedpolicy.c b/cpukit/posix/src/pthreadattrsetschedpolicy.c new file mode 100644 index 0000000000..ab61e000ed --- /dev/null +++ b/cpukit/posix/src/pthreadattrsetschedpolicy.c @@ -0,0 +1,43 @@ +/* + * 13.5.1 Thread Creation Scheduling Attributes, P1003.1c/Draft 10, p. 120 + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/pthread.h> + +int pthread_attr_setschedpolicy( + pthread_attr_t *attr, + int policy +) +{ + if ( !attr || !attr->is_initialized ) + return EINVAL; + + switch ( policy ) { + case SCHED_OTHER: + case SCHED_FIFO: + case SCHED_RR: + case SCHED_SPORADIC: + attr->schedpolicy = policy; + return 0; + + default: + return ENOTSUP; + } +} diff --git a/cpukit/posix/src/pthreadattrsetscope.c b/cpukit/posix/src/pthreadattrsetscope.c new file mode 100644 index 0000000000..8c6d1c3f9c --- /dev/null +++ b/cpukit/posix/src/pthreadattrsetscope.c @@ -0,0 +1,43 @@ +/* + * 13.5.1 Thread Creation Scheduling Attributes, P1003.1c/Draft 10, p. 120 + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/pthread.h> + +int pthread_attr_setscope( + pthread_attr_t *attr, + int contentionscope +) +{ + if ( !attr || !attr->is_initialized ) + return EINVAL; + + switch ( contentionscope ) { + case PTHREAD_SCOPE_PROCESS: + attr->contentionscope = contentionscope; + return 0; + + case PTHREAD_SCOPE_SYSTEM: + return ENOTSUP; + + default: + return EINVAL; + } +} diff --git a/cpukit/posix/src/pthreadattrsetstack.c b/cpukit/posix/src/pthreadattrsetstack.c new file mode 100644 index 0000000000..f97d3ac885 --- /dev/null +++ b/cpukit/posix/src/pthreadattrsetstack.c @@ -0,0 +1,42 @@ +/* + * 16.1.1 Thread Creation Attributes + * + * COPYRIGHT (c) 1989-2010. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#if HAVE_DECL_PTHREAD_ATTR_SETSTACK +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/pthread.h> + +int pthread_attr_setstack( + pthread_attr_t *attr, + void *stackaddr, + size_t stacksize +) +{ + if ( !attr || !attr->is_initialized ) + return EINVAL; + + if (stacksize < PTHREAD_MINIMUM_STACK_SIZE) + attr->stacksize = PTHREAD_MINIMUM_STACK_SIZE; + else + attr->stacksize = stacksize; + + attr->stackaddr = stackaddr; + return 0; +} +#endif diff --git a/cpukit/posix/src/pthreadattrsetstackaddr.c b/cpukit/posix/src/pthreadattrsetstackaddr.c new file mode 100644 index 0000000000..b7ed212546 --- /dev/null +++ b/cpukit/posix/src/pthreadattrsetstackaddr.c @@ -0,0 +1,31 @@ +/* + * 16.1.1 Thread Creation Attributes, P1003.1c/Draft 10, p, 140 + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +int pthread_attr_setstackaddr( + pthread_attr_t *attr, + void *stackaddr +) +{ + if ( !attr || !attr->is_initialized ) + return EINVAL; + + attr->stackaddr = stackaddr; + return 0; +} diff --git a/cpukit/posix/src/pthreadattrsetstacksize.c b/cpukit/posix/src/pthreadattrsetstacksize.c new file mode 100644 index 0000000000..9598a8a7d7 --- /dev/null +++ b/cpukit/posix/src/pthreadattrsetstacksize.c @@ -0,0 +1,37 @@ +/* + * 16.1.1 Thread Creation Attributes, P1003.1c/Draft 10, p, 140 + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/pthread.h> + +int pthread_attr_setstacksize( + pthread_attr_t *attr, + size_t stacksize +) +{ + if ( !attr || !attr->is_initialized ) + return EINVAL; + + if (stacksize < PTHREAD_MINIMUM_STACK_SIZE) + attr->stacksize = PTHREAD_MINIMUM_STACK_SIZE; + else + attr->stacksize = stacksize; + return 0; +} diff --git a/cpukit/posix/src/pthreadcreate.c b/cpukit/posix/src/pthreadcreate.c new file mode 100644 index 0000000000..d7f08a5527 --- /dev/null +++ b/cpukit/posix/src/pthreadcreate.c @@ -0,0 +1,232 @@ +/* + * 16.1.2 Thread Creation, P1003.1c/Draft 10, p. 144 + */ + +/* COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/score/thread.h> +#include <rtems/posix/pthread.h> +#include <rtems/posix/priority.h> +#include <rtems/posix/time.h> +#include <rtems/score/apimutex.h> + +static inline size_t _POSIX_Threads_Ensure_minimum_stack ( + size_t size +) +{ + if ( size >= PTHREAD_MINIMUM_STACK_SIZE ) + return size; + return PTHREAD_MINIMUM_STACK_SIZE; +} + + +int pthread_create( + pthread_t *thread, + const pthread_attr_t *attr, + void *(*start_routine)( void * ), + void *arg +) +{ + const pthread_attr_t *the_attr; + Priority_Control core_priority; + Thread_CPU_budget_algorithms budget_algorithm; + Thread_CPU_budget_algorithm_callout budget_callout; + bool is_fp; + bool status; + Thread_Control *the_thread; + POSIX_API_Control *api; + int schedpolicy = SCHED_RR; + struct sched_param schedparam; + Objects_Name name; + int rc; + + if ( !start_routine ) + return EFAULT; + + the_attr = (attr) ? attr : &_POSIX_Threads_Default_attributes; + + if ( !the_attr->is_initialized ) + return EINVAL; + + /* + * Core Thread Initialize ensures we get the minimum amount of + * stack space if it is allowed to allocate it itself. + * + * NOTE: If the user provides the stack we will let it drop below + * twice the minimum. + */ + if ( the_attr->stackaddr && !_Stack_Is_enough(the_attr->stacksize) ) + return EINVAL; + + #if 0 + int cputime_clock_allowed; /* see time.h */ + rtems_set_errno_and_return_minus_one( ENOSYS ); + #endif + + /* + * P1003.1c/Draft 10, p. 121. + * + * If inheritsched is set to PTHREAD_INHERIT_SCHED, then this thread + * inherits scheduling attributes from the creating thread. If it is + * PTHREAD_EXPLICIT_SCHED, then scheduling parameters come from the + * attributes structure. + */ + switch ( the_attr->inheritsched ) { + case PTHREAD_INHERIT_SCHED: + api = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ]; + schedpolicy = api->schedpolicy; + schedparam = api->schedparam; + break; + + case PTHREAD_EXPLICIT_SCHED: + schedpolicy = the_attr->schedpolicy; + schedparam = the_attr->schedparam; + break; + + default: + return EINVAL; + } + + /* + * Check the contentionscope since rtems only supports PROCESS wide + * contention (i.e. no system wide contention). + */ + if ( the_attr->contentionscope != PTHREAD_SCOPE_PROCESS ) + return ENOTSUP; + + /* + * Interpret the scheduling parameters. + */ + if ( !_POSIX_Priority_Is_valid( schedparam.sched_priority ) ) + return EINVAL; + + core_priority = _POSIX_Priority_To_core( schedparam.sched_priority ); + + /* + * Set the core scheduling policy information. + */ + rc = _POSIX_Thread_Translate_sched_param( + schedpolicy, + &schedparam, + &budget_algorithm, + &budget_callout + ); + if ( rc ) + return rc; + + /* + * Currently all POSIX threads are floating point if the hardware + * supports it. + */ + #if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE ) + is_fp = true; + #else + is_fp = false; + #endif + + /* + * Lock the allocator mutex for protection + */ + _RTEMS_Lock_allocator(); + + /* + * Allocate the thread control block. + * + * NOTE: Global threads are not currently supported. + */ + the_thread = _POSIX_Threads_Allocate(); + if ( !the_thread ) { + _RTEMS_Unlock_allocator(); + return EAGAIN; + } + + /* + * Initialize the core thread for this task. + */ + name.name_p = NULL; /* posix threads don't have a name by default */ + status = _Thread_Initialize( + &_POSIX_Threads_Information, + the_thread, + the_attr->stackaddr, + _POSIX_Threads_Ensure_minimum_stack(the_attr->stacksize), + is_fp, + core_priority, + true, /* preemptible */ + budget_algorithm, + budget_callout, + 0, /* isr level */ + name /* posix threads don't have a name */ + ); + + if ( !status ) { + _POSIX_Threads_Free( the_thread ); + _RTEMS_Unlock_allocator(); + return EAGAIN; + } + + /* + * finish initializing the per API structure + */ + api = the_thread->API_Extensions[ THREAD_API_POSIX ]; + + api->Attributes = *the_attr; + api->detachstate = the_attr->detachstate; + api->schedpolicy = schedpolicy; + api->schedparam = schedparam; + + /* + * POSIX threads are allocated and started in one operation. + */ + status = _Thread_Start( + the_thread, + THREAD_START_POINTER, + start_routine, + arg, + 0 /* unused */ + ); + + #if defined(RTEMS_DEBUG) + /* + * _Thread_Start only fails if the thread was in the incorrect state + * + * NOTE: This can only happen if someone slips in and touches the + * thread while we are creating it. + */ + if ( !status ) { + _POSIX_Threads_Free( the_thread ); + _RTEMS_Unlock_allocator(); + return EINVAL; + } + #endif + + if ( schedpolicy == SCHED_SPORADIC ) { + _Watchdog_Insert_ticks( + &api->Sporadic_timer, + _Timespec_To_ticks( &api->schedparam.sched_ss_repl_period ) + ); + } + + /* + * Return the id and indicate we successfully created the thread + */ + *thread = the_thread->Object.id; + + _RTEMS_Unlock_allocator(); + return 0; +} diff --git a/cpukit/posix/src/pthreaddetach.c b/cpukit/posix/src/pthreaddetach.c new file mode 100644 index 0000000000..6078fcc97e --- /dev/null +++ b/cpukit/posix/src/pthreaddetach.c @@ -0,0 +1,51 @@ +/* + * 16.1.4 Detaching a Thread, P1003.1c/Draft 10, p. 149 + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/score/thread.h> +#include <rtems/posix/pthread.h> + +int pthread_detach( + pthread_t thread +) +{ + register Thread_Control *the_thread; + POSIX_API_Control *api; + Objects_Locations location; + + the_thread = _Thread_Get( thread, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + + api = the_thread->API_Extensions[ THREAD_API_POSIX ]; + api->detachstate = PTHREAD_CREATE_DETACHED; + _Thread_Enable_dispatch(); + return 0; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: +#endif + case OBJECTS_ERROR: + break; + } + + return ESRCH; +} diff --git a/cpukit/posix/src/pthreadequal.c b/cpukit/posix/src/pthreadequal.c new file mode 100644 index 0000000000..9944026f3e --- /dev/null +++ b/cpukit/posix/src/pthreadequal.c @@ -0,0 +1,93 @@ +/* + * 16.1.7 Compare Thread IDs, p1003.1c/Draft 10, p. 153 + * + * NOTE: POSIX does not define the behavior when either thread id is invalid. + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/pthread.h> +#include <rtems/score/thread.h> + +int pthread_equal( + pthread_t t1, + pthread_t t2 +) +{ + /* + * If the system is configured for debug, then we will do everything we + * can to insure that both ids are valid. Otherwise, we will do the + * cheapest possible thing to determine if they are equal. + */ + +#ifndef RTEMS_DEBUG + return _Objects_Are_ids_equal( t1, t2 ); +#else + int status; + Objects_Locations location; + + /* + * By default this is not a match. + */ + + status = 0; + + /* + * Validate the first id and return 0 if it is not valid + */ + + (void) _Thread_Get( t1, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + + /* + * Validate the second id and return 0 if it is not valid + */ + + (void) _Thread_Get( t2, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + status = _Objects_Are_ids_equal( t1, t2 ); + _Thread_Unnest_dispatch(); + _Thread_Enable_dispatch(); + break; + + case OBJECTS_ERROR: +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: +#endif + /* t1 must have been valid so exit the critical section */ + _Thread_Enable_dispatch(); + /* return status == 0 */ + break; + } + break; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: +#endif + case OBJECTS_ERROR: + /* return status == 0 */ + break; + } + + return status; +#endif +} diff --git a/cpukit/posix/src/pthreadexit.c b/cpukit/posix/src/pthreadexit.c new file mode 100644 index 0000000000..9efe9d9a47 --- /dev/null +++ b/cpukit/posix/src/pthreadexit.c @@ -0,0 +1,67 @@ +/* + * 16.1.5.1 Thread Termination, p1003.1c/Draft 10, p. 150 + * + * NOTE: Key destructors are executed in the POSIX api delete extension. + * + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/score/apimutex.h> +#include <rtems/score/thread.h> +#include <rtems/posix/pthread.h> + +void _POSIX_Thread_Exit( + Thread_Control *the_thread, + void *value_ptr +) +{ + Objects_Information *the_information; + + the_information = _Objects_Get_information_id( the_thread->Object.id ); + + /* + * The_information has to be non-NULL. Otherwise, we couldn't be + * running in a thread of this API and class. + * + * NOTE: Lock and unlock in different order so we do not throw a + * fatal error when locking the allocator mutex. And after + * we unlock, we want to defer the context switch until we + * are ready to be switched out. Otherwise, an ISR could + * occur and preempt us out while we still hold the + * allocator mutex. + */ + + _RTEMS_Lock_allocator(); + _Thread_Disable_dispatch(); + + the_thread->Wait.return_argument = value_ptr; + + _Thread_Close( the_information, the_thread ); + + _POSIX_Threads_Free( the_thread ); + + _RTEMS_Unlock_allocator(); + _Thread_Enable_dispatch(); +} + +void pthread_exit( + void *value_ptr +) +{ + _POSIX_Thread_Exit( _Thread_Executing, value_ptr ); +} diff --git a/cpukit/posix/src/pthreadgetcpuclockid.c b/cpukit/posix/src/pthreadgetcpuclockid.c new file mode 100644 index 0000000000..2ba0dcc3e0 --- /dev/null +++ b/cpukit/posix/src/pthreadgetcpuclockid.c @@ -0,0 +1,30 @@ +/* + * 20.1.6 Accessing a Thread CPU-time Clock, P1003.4b/Draft 8, p. 58 + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/seterr.h> + +int pthread_getcpuclockid( + pthread_t pid, + clockid_t *clock_id +) +{ + rtems_set_errno_and_return_minus_one( ENOSYS ); +} diff --git a/cpukit/posix/src/pthreadgetcputime.c b/cpukit/posix/src/pthreadgetcputime.c new file mode 100644 index 0000000000..7c9bb46c7b --- /dev/null +++ b/cpukit/posix/src/pthreadgetcputime.c @@ -0,0 +1,31 @@ +/* + * 20.1.7 CPU-time Clock Thread Creation Attribute, P1003.4b/Draft 8, p. 59 + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +int pthread_attr_getcputime( + pthread_attr_t *attr, + int *clock_allowed +) +{ + if ( !attr || !attr->is_initialized || !clock_allowed ) + return EINVAL; + + *clock_allowed = attr->cputime_clock_allowed; + return 0; +} diff --git a/cpukit/posix/src/pthreadgetschedparam.c b/cpukit/posix/src/pthreadgetschedparam.c new file mode 100644 index 0000000000..b8e0a83153 --- /dev/null +++ b/cpukit/posix/src/pthreadgetschedparam.c @@ -0,0 +1,63 @@ +/* + * 13.5.2 Dynamic Thread Scheduling Parameters Access, + * P1003.1c/Draft 10, p. 124 + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/pthread.h> +#include <rtems/posix/priority.h> + +int pthread_getschedparam( + pthread_t thread, + int *policy, + struct sched_param *param +) +{ + Objects_Locations location; + POSIX_API_Control *api; + register Thread_Control *the_thread; + + if ( !policy || !param ) + return EINVAL; + + the_thread = _Thread_Get( thread, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + api = the_thread->API_Extensions[ THREAD_API_POSIX ]; + if ( policy ) + *policy = api->schedpolicy; + if ( param ) { + *param = api->schedparam; + param->sched_priority = + _POSIX_Priority_From_core( the_thread->current_priority ); + } + _Thread_Enable_dispatch(); + return 0; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: +#endif + case OBJECTS_ERROR: + break; + } + + return ESRCH; + +} diff --git a/cpukit/posix/src/pthreadinitthreads.c b/cpukit/posix/src/pthreadinitthreads.c new file mode 100644 index 0000000000..b7c0fdec3b --- /dev/null +++ b/cpukit/posix/src/pthreadinitthreads.c @@ -0,0 +1,87 @@ +/* + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <errno.h> +#include <pthread.h> +#include <limits.h> + +#include <rtems/system.h> +#include <rtems/config.h> +#include <rtems/score/apiext.h> +#include <rtems/score/stack.h> +#include <rtems/score/thread.h> +#include <rtems/score/userext.h> +#include <rtems/score/wkspace.h> +#include <rtems/posix/cancel.h> +#include <rtems/posix/pthread.h> +#include <rtems/posix/priority.h> +#include <rtems/posix/psignal.h> +#include <rtems/posix/config.h> +#include <rtems/posix/key.h> +#include <rtems/posix/time.h> + +/*PAGE + * + * _POSIX_Threads_Initialize_user_threads_body + * + * This routine creates and starts all configured user + * initialzation threads. + * + * Input parameters: NONE + * + * Output parameters: NONE + */ + +void _POSIX_Threads_Initialize_user_threads_body(void) +{ + int status; + uint32_t index; + uint32_t maximum; + posix_initialization_threads_table *user_threads; + pthread_t thread_id; + pthread_attr_t attr; + + user_threads = Configuration_POSIX_API.User_initialization_threads_table; + maximum = Configuration_POSIX_API.number_of_initialization_threads; + + if ( !user_threads || maximum == 0 ) + return; + + /* + * Be careful .. if the default attribute set changes, this may need to. + * + * Setting the attributes explicitly is critical, since we don't want + * to inherit the idle tasks attributes. + */ + + for ( index=0 ; index < maximum ; index++ ) { + /* + * There is no way for these calls to fail in this situation. + */ + (void) pthread_attr_init( &attr ); + (void) pthread_attr_setinheritsched( &attr, PTHREAD_EXPLICIT_SCHED ); + (void) pthread_attr_setstacksize(&attr, user_threads[ index ].stack_size); + + status = pthread_create( + &thread_id, + &attr, + user_threads[ index ].thread_entry, + NULL + ); + if ( status ) + _Internal_error_Occurred( INTERNAL_ERROR_POSIX_API, true, status ); + } +} + diff --git a/cpukit/posix/src/pthreadjoin.c b/cpukit/posix/src/pthreadjoin.c new file mode 100644 index 0000000000..8ee9888b94 --- /dev/null +++ b/cpukit/posix/src/pthreadjoin.c @@ -0,0 +1,75 @@ +/* + * 16.1.3 Wait for Thread Termination, P1003.1c/Draft 10, p. 147 + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/score/thread.h> +#include <rtems/posix/pthread.h> + +int pthread_join( + pthread_t thread, + void **value_ptr +) +{ + register Thread_Control *the_thread; + POSIX_API_Control *api; + Objects_Locations location; + void *return_pointer; + + the_thread = _Thread_Get( thread, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + api = the_thread->API_Extensions[ THREAD_API_POSIX ]; + + if ( api->detachstate == PTHREAD_CREATE_DETACHED ) { + _Thread_Enable_dispatch(); + return EINVAL; + } + + if ( _Thread_Is_executing( the_thread ) ) { + _Thread_Enable_dispatch(); + return EDEADLK; + } + + /* + * Put ourself on the threads join list + */ + + _Thread_Executing->Wait.return_argument = &return_pointer; + + _Thread_queue_Enter_critical_section( &api->Join_List ); + + _Thread_queue_Enqueue( &api->Join_List, WATCHDOG_NO_TIMEOUT ); + + _Thread_Enable_dispatch(); + + if ( value_ptr ) + *value_ptr = return_pointer; + return 0; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: +#endif + case OBJECTS_ERROR: + break; + } + + return ESRCH; +} diff --git a/cpukit/posix/src/pthreadkill.c b/cpukit/posix/src/pthreadkill.c new file mode 100644 index 0000000000..777ee6ad0c --- /dev/null +++ b/cpukit/posix/src/pthreadkill.c @@ -0,0 +1,80 @@ +/* + * 3.3.10 Send a Signal to a Thread, P1003.1c/D10, p. 43 + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <signal.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/pthread.h> +#include <rtems/posix/psignal.h> +#include <rtems/score/isr.h> +#include <rtems/seterr.h> + +int pthread_kill( + pthread_t thread, + int sig +) +{ + POSIX_API_Control *api; + Thread_Control *the_thread; + Objects_Locations location; + + if ( !sig ) + rtems_set_errno_and_return_minus_one( EINVAL ); + + if ( !is_valid_signo(sig) ) + rtems_set_errno_and_return_minus_one( EINVAL ); + + the_thread = _Thread_Get( thread, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + /* + * If sig == 0 then just validate arguments + */ + + api = the_thread->API_Extensions[ THREAD_API_POSIX ]; + + if ( sig ) { + + if ( _POSIX_signals_Vectors[ sig ].sa_handler == SIG_IGN ) { + _Thread_Enable_dispatch(); + return 0; + } + + /* XXX critical section */ + + api->signals_pending |= signo_to_mask( sig ); + + (void) _POSIX_signals_Unblock_thread( the_thread, sig, NULL ); + + if ( _ISR_Is_in_progress() && _Thread_Is_executing( the_thread ) ) + _Thread_Dispatch_necessary = true; + } + _Thread_Enable_dispatch(); + return 0; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: +#endif + case OBJECTS_ERROR: + break; + } + + rtems_set_errno_and_return_minus_one( ESRCH ); +} diff --git a/cpukit/posix/src/pthreadonce.c b/cpukit/posix/src/pthreadonce.c new file mode 100644 index 0000000000..8e4a9dc6d8 --- /dev/null +++ b/cpukit/posix/src/pthreadonce.c @@ -0,0 +1,44 @@ +/* + * 16.1.8 Dynamic Package Initialization, P1003.1c/Draft 10, p. 154 + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +#include <rtems.h> +#include <rtems/system.h> +#include <rtems/score/thread.h> + +int pthread_once( + pthread_once_t *once_control, + void (*init_routine)(void) +) +{ + if ( !once_control || !init_routine ) + return EINVAL; + + if ( !once_control->init_executed ) { + rtems_mode saveMode; + rtems_task_mode(RTEMS_NO_PREEMPT, RTEMS_PREEMPT_MASK, &saveMode); + if ( !once_control->init_executed ) { + once_control->is_initialized = true; + once_control->init_executed = true; + (*init_routine)(); + } + rtems_task_mode(saveMode, RTEMS_PREEMPT_MASK, &saveMode); + } + return 0; +} diff --git a/cpukit/posix/src/pthreadself.c b/cpukit/posix/src/pthreadself.c new file mode 100644 index 0000000000..c1baf85177 --- /dev/null +++ b/cpukit/posix/src/pthreadself.c @@ -0,0 +1,27 @@ +/* + * 16.1.6 Get Calling Thread's ID, p1003.1c/Draft 10, p. 152 + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/score/thread.h> + +pthread_t pthread_self( void ) +{ + return _Thread_Executing->Object.id; +} diff --git a/cpukit/posix/src/pthreadsetcputime.c b/cpukit/posix/src/pthreadsetcputime.c new file mode 100644 index 0000000000..70b9594ab9 --- /dev/null +++ b/cpukit/posix/src/pthreadsetcputime.c @@ -0,0 +1,38 @@ +/* + * 20.1.7 CPU-time Clock Thread Creation Attribute, P1003.4b/Draft 8, p. 59 + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +int pthread_attr_setcputime( + pthread_attr_t *attr, + int clock_allowed +) +{ + if ( !attr || !attr->is_initialized ) + return EINVAL; + + switch ( clock_allowed ) { + case CLOCK_ENABLED: + case CLOCK_DISABLED: + attr->cputime_clock_allowed = clock_allowed; + return 0; + + default: + return EINVAL; + } +} diff --git a/cpukit/posix/src/pthreadsetschedparam.c b/cpukit/posix/src/pthreadsetschedparam.c new file mode 100644 index 0000000000..14edfa0218 --- /dev/null +++ b/cpukit/posix/src/pthreadsetschedparam.c @@ -0,0 +1,107 @@ +/* + * 13.5.2 Dynamic Thread Scheduling Parameters Access, + * P1003.1c/Draft 10, p. 124 + */ + +/* COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/pthread.h> +#include <rtems/posix/priority.h> +#include <rtems/posix/time.h> + +int pthread_setschedparam( + pthread_t thread, + int policy, + struct sched_param *param +) +{ + register Thread_Control *the_thread; + POSIX_API_Control *api; + Thread_CPU_budget_algorithms budget_algorithm; + Thread_CPU_budget_algorithm_callout budget_callout; + Objects_Locations location; + int rc; + + /* + * Check all the parameters + */ + if ( !param ) + return EINVAL; + + rc = _POSIX_Thread_Translate_sched_param( + policy, + param, + &budget_algorithm, + &budget_callout + ); + if ( rc ) + return rc; + + /* + * Actually change the scheduling policy and parameters + */ + the_thread = _Thread_Get( thread, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + api = the_thread->API_Extensions[ THREAD_API_POSIX ]; + + if ( api->schedpolicy == SCHED_SPORADIC ) + (void) _Watchdog_Remove( &api->Sporadic_timer ); + + api->schedpolicy = policy; + api->schedparam = *param; + the_thread->budget_algorithm = budget_algorithm; + the_thread->budget_callout = budget_callout; + + switch ( api->schedpolicy ) { + case SCHED_OTHER: + case SCHED_FIFO: + case SCHED_RR: + the_thread->cpu_time_budget = _Thread_Ticks_per_timeslice; + + the_thread->real_priority = + _POSIX_Priority_To_core( api->schedparam.sched_priority ); + + _Thread_Change_priority( + the_thread, + the_thread->real_priority, + true + ); + break; + + case SCHED_SPORADIC: + api->ss_high_priority = api->schedparam.sched_priority; + _Watchdog_Remove( &api->Sporadic_timer ); + _POSIX_Threads_Sporadic_budget_TSR( 0, the_thread ); + break; + } + + _Thread_Enable_dispatch(); + return 0; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: +#endif + case OBJECTS_ERROR: + break; + } + + return ESRCH; +} diff --git a/cpukit/posix/src/pthreadsigmask.c b/cpukit/posix/src/pthreadsigmask.c new file mode 100644 index 0000000000..c97e75a89e --- /dev/null +++ b/cpukit/posix/src/pthreadsigmask.c @@ -0,0 +1,72 @@ +/* + * 3.3.5 Examine and Change Blocked Signals, P1003.1b-1993, p. 73 + * + * NOTE: P1003.1c/D10, p. 37 adds pthread_sigmask(). + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <signal.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/pthread.h> +#include <rtems/posix/psignal.h> +#include <rtems/seterr.h> + +int pthread_sigmask( + int how, + const sigset_t *set, + sigset_t *oset +) +{ + POSIX_API_Control *api; + + if ( !set && !oset ) + rtems_set_errno_and_return_minus_one( EINVAL ); + + api = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ]; + + if ( oset ) + *oset = api->signals_blocked; + + if ( !set ) + return 0; + + switch ( how ) { + case SIG_BLOCK: + api->signals_blocked |= *set; + break; + case SIG_UNBLOCK: + api->signals_blocked &= ~*set; + break; + case SIG_SETMASK: + api->signals_blocked = *set; + break; + default: + rtems_set_errno_and_return_minus_one( EINVAL ); + } + + /* XXX are there critical section problems here? */ + + /* XXX evaluate the new set */ + + if ( ~api->signals_blocked & + (api->signals_pending | _POSIX_signals_Pending) ) { + _Thread_Dispatch(); + } + + return 0; +} diff --git a/cpukit/posix/src/ptimer.c b/cpukit/posix/src/ptimer.c new file mode 100644 index 0000000000..6ded55c0a6 --- /dev/null +++ b/cpukit/posix/src/ptimer.c @@ -0,0 +1,72 @@ +/* + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * ptimer.c,v 1.1 1996/06/03 16:29:58 joel Exp + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <time.h> +#include <errno.h> +#include <limits.h> /* _POSIX_PATH_MAX */ + +#include <rtems/system.h> +#include <rtems/config.h> +#include <rtems/score/isr.h> +#include <rtems/score/thread.h> +#include <rtems/score/tod.h> + +#include <rtems/posix/time.h> + +/************************************/ +/* These includes are now necessary */ +/************************************/ + +#include <unistd.h> +#include <rtems/rtems/status.h> +#include <rtems/rtems/types.h> +#include <rtems/rtems/timer.h> +#include <rtems/rtems/clock.h> +#include <rtems/posix/psignal.h> +#include <rtems/score/wkspace.h> +#include <pthread.h> +#include <stdio.h> +#include <signal.h> + +#include <rtems/posix/timer.h> + +/* + * _POSIX_Timer_Manager_initialization + * + * Description: + * + * Initialize the internal structure in which the data of all + * the timers are stored + */ + +void _POSIX_Timer_Manager_initialization(void) +{ + _Objects_Initialize_information( + &_POSIX_Timer_Information, /* object information table */ + OBJECTS_POSIX_API, /* object API */ + OBJECTS_POSIX_TIMERS, /* object class */ + Configuration_POSIX_API.maximum_timers, + /* maximum objects of this class */ + sizeof( POSIX_Timer_Control ), + /* size of this object's control block */ + true, /* true if names for this object are strings */ + _POSIX_PATH_MAX /* maximum length of each object's name */ +#if defined(RTEMS_MULTIPROCESSING) + , + false, /* true if this is a global object class */ + NULL /* Proxy extraction support callout */ +#endif + ); +} diff --git a/cpukit/posix/src/rwlockattrdestroy.c b/cpukit/posix/src/rwlockattrdestroy.c new file mode 100644 index 0000000000..aa4b6e3345 --- /dev/null +++ b/cpukit/posix/src/rwlockattrdestroy.c @@ -0,0 +1,41 @@ +/* + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/score/object.h> +#include <rtems/score/states.h> +#include <rtems/score/watchdog.h> +#include <rtems/posix/cond.h> +#include <rtems/posix/time.h> +#include <rtems/posix/mutex.h> + +/*PAGE + * + * RWLock Initialization Attributes + */ + +int pthread_rwlockattr_destroy( + pthread_rwlockattr_t *attr +) +{ + if ( !attr || attr->is_initialized == false ) + return EINVAL; + + attr->is_initialized = false; + return 0; +} diff --git a/cpukit/posix/src/rwlockattrgetpshared.c b/cpukit/posix/src/rwlockattrgetpshared.c new file mode 100644 index 0000000000..b0536df1b0 --- /dev/null +++ b/cpukit/posix/src/rwlockattrgetpshared.c @@ -0,0 +1,37 @@ +/* + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +/*PAGE + * + * RWLock Attributes Get Process Shared + */ + +int pthread_rwlockattr_getpshared( + const pthread_rwlockattr_t *attr, + int *pshared +) +{ + if ( !attr ) + return EINVAL; + + if ( !attr->is_initialized ) + return EINVAL; + + *pshared = attr->process_shared; + return 0; +} diff --git a/cpukit/posix/src/rwlockattrinit.c b/cpukit/posix/src/rwlockattrinit.c new file mode 100644 index 0000000000..77f5992038 --- /dev/null +++ b/cpukit/posix/src/rwlockattrinit.c @@ -0,0 +1,36 @@ +/* + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> + +/*PAGE + * + * RWLock Attributes Initialization + */ + +int pthread_rwlockattr_init( + pthread_rwlockattr_t *attr +) +{ + if ( !attr ) + return EINVAL; + + attr->is_initialized = true; + attr->process_shared = PTHREAD_PROCESS_PRIVATE; + return 0; +} diff --git a/cpukit/posix/src/rwlockattrsetpshared.c b/cpukit/posix/src/rwlockattrsetpshared.c new file mode 100644 index 0000000000..92fc38fa9e --- /dev/null +++ b/cpukit/posix/src/rwlockattrsetpshared.c @@ -0,0 +1,44 @@ +/* + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +/*PAGE + * + * RWLock Attributes Set Process Shared + */ + +int pthread_rwlockattr_setpshared( + pthread_rwlockattr_t *attr, + int pshared +) +{ + if ( !attr ) + return EINVAL; + + if ( !attr->is_initialized ) + return EINVAL; + + switch ( pshared ) { + case PTHREAD_PROCESS_SHARED: + case PTHREAD_PROCESS_PRIVATE: + attr->process_shared = pshared; + return 0; + + default: + return EINVAL; + } +} diff --git a/cpukit/posix/src/sched_getparam.c b/cpukit/posix/src/sched_getparam.c new file mode 100644 index 0000000000..c25286bdc3 --- /dev/null +++ b/cpukit/posix/src/sched_getparam.c @@ -0,0 +1,30 @@ +/* + * 13.3.2 Set Scheduling Parameters, P1003.1b-1993, p. 253 + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <sched.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/seterr.h> + +int sched_getparam( + pid_t pid __attribute__((unused)), + struct sched_param *param __attribute__((unused)) +) +{ + rtems_set_errno_and_return_minus_one( ENOSYS ); +} diff --git a/cpukit/posix/src/sched_getprioritymax.c b/cpukit/posix/src/sched_getprioritymax.c new file mode 100644 index 0000000000..9f8965e4d5 --- /dev/null +++ b/cpukit/posix/src/sched_getprioritymax.c @@ -0,0 +1,41 @@ +/* + * 13.3.6 Get Scheduling Parameter Limits, P1003.1b-1993, p. 258 + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <sched.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/seterr.h> +#include <rtems/posix/priority.h> + +int sched_get_priority_max( + int policy +) +{ + switch ( policy ) { + case SCHED_OTHER: + case SCHED_FIFO: + case SCHED_RR: + case SCHED_SPORADIC: + break; + + default: + rtems_set_errno_and_return_minus_one( EINVAL ); + } + + return POSIX_SCHEDULER_MAXIMUM_PRIORITY; +} diff --git a/cpukit/posix/src/sched_getprioritymin.c b/cpukit/posix/src/sched_getprioritymin.c new file mode 100644 index 0000000000..88e1170f12 --- /dev/null +++ b/cpukit/posix/src/sched_getprioritymin.c @@ -0,0 +1,41 @@ +/* + * 13.3.6 Get Scheduling Parameter Limits, P1003.1b-1993, p. 258 + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <sched.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/seterr.h> +#include <rtems/posix/priority.h> + +int sched_get_priority_min( + int policy +) +{ + switch ( policy ) { + case SCHED_OTHER: + case SCHED_FIFO: + case SCHED_RR: + case SCHED_SPORADIC: + break; + + default: + rtems_set_errno_and_return_minus_one( EINVAL ); + } + + return POSIX_SCHEDULER_MINIMUM_PRIORITY; +} diff --git a/cpukit/posix/src/sched_getscheduler.c b/cpukit/posix/src/sched_getscheduler.c new file mode 100644 index 0000000000..8afbcfd486 --- /dev/null +++ b/cpukit/posix/src/sched_getscheduler.c @@ -0,0 +1,33 @@ +/* + * 13.3.4 Get Scheduling Policy, P1003.1b-1993, p. 256 + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <sched.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/score/tod.h> +#include <rtems/score/thread.h> +#include <rtems/seterr.h> +#include <rtems/posix/priority.h> +#include <rtems/posix/time.h> + +int sched_getscheduler( + pid_t pid __attribute__((unused)) +) +{ + rtems_set_errno_and_return_minus_one( ENOSYS ); +} diff --git a/cpukit/posix/src/sched_rr_get_interval.c b/cpukit/posix/src/sched_rr_get_interval.c new file mode 100644 index 0000000000..c9e3e280ca --- /dev/null +++ b/cpukit/posix/src/sched_rr_get_interval.c @@ -0,0 +1,45 @@ +/* + * 13.3.6 Get Scheduling Parameter Limits, P1003.1b-1993, p. 258 + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <unistd.h> /* getpid */ +#include <sched.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/score/tod.h> +#include <rtems/score/thread.h> +#include <rtems/score/timespec.h> +#include <rtems/seterr.h> + +int sched_rr_get_interval( + pid_t pid, + struct timespec *interval +) +{ + /* + * Only supported for the "calling process" (i.e. this node). + */ + + if ( pid && pid != getpid() ) + rtems_set_errno_and_return_minus_one( ESRCH ); + + if ( !interval ) + rtems_set_errno_and_return_minus_one( EINVAL ); + + _Timespec_From_ticks( _Thread_Ticks_per_timeslice, interval ); + return 0; +} diff --git a/cpukit/posix/src/sched_setparam.c b/cpukit/posix/src/sched_setparam.c new file mode 100644 index 0000000000..155ed2d11b --- /dev/null +++ b/cpukit/posix/src/sched_setparam.c @@ -0,0 +1,34 @@ +/* + * 13.3.1 Set Scheduling Parameters, P1003.1b-1993, p. 252 + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <sched.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/score/tod.h> +#include <rtems/score/thread.h> +#include <rtems/seterr.h> +#include <rtems/posix/priority.h> +#include <rtems/posix/time.h> + +int sched_setparam( + pid_t pid __attribute__((unused)), + const struct sched_param *param __attribute__((unused)) +) +{ + rtems_set_errno_and_return_minus_one( ENOSYS ); +} diff --git a/cpukit/posix/src/sched_setscheduler.c b/cpukit/posix/src/sched_setscheduler.c new file mode 100644 index 0000000000..f0bb5496fa --- /dev/null +++ b/cpukit/posix/src/sched_setscheduler.c @@ -0,0 +1,36 @@ +/* + * 13.3.3 Set Scheduling Policy and Scheduling Parameters, + * P1003.1b-1993, p. 254 + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <sched.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/score/tod.h> +#include <rtems/score/thread.h> +#include <rtems/seterr.h> +#include <rtems/posix/priority.h> +#include <rtems/posix/time.h> + +int sched_setscheduler( + pid_t pid __attribute__((unused)), + int policy __attribute__((unused)), + const struct sched_param *param __attribute__((unused)) +) +{ + rtems_set_errno_and_return_minus_one( ENOSYS ); +} diff --git a/cpukit/posix/src/sched_yield.c b/cpukit/posix/src/sched_yield.c new file mode 100644 index 0000000000..b6c5c4fce4 --- /dev/null +++ b/cpukit/posix/src/sched_yield.c @@ -0,0 +1,35 @@ +/* + * 13.3.5 Yield Processor, P1003.1b-1993, p. 257 + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <sched.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/score/scheduler.h> +#include <rtems/score/tod.h> +#include <rtems/score/thread.h> +#include <rtems/seterr.h> +#include <rtems/posix/priority.h> +#include <rtems/posix/time.h> + +int sched_yield( void ) +{ + _Thread_Disable_dispatch(); + _Scheduler_Yield(); + _Thread_Enable_dispatch(); + return 0; +} diff --git a/cpukit/posix/src/semaphore.c b/cpukit/posix/src/semaphore.c new file mode 100644 index 0000000000..e84bea87a4 --- /dev/null +++ b/cpukit/posix/src/semaphore.c @@ -0,0 +1,60 @@ +/* + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdarg.h> + +#include <errno.h> +#include <fcntl.h> +#include <pthread.h> +#include <semaphore.h> +#include <limits.h> + +#include <rtems/system.h> +#include <rtems/config.h> +#include <rtems/score/object.h> +#include <rtems/posix/semaphore.h> +#include <rtems/posix/time.h> +#include <rtems/seterr.h> + +/*PAGE + * + * _POSIX_Semaphore_Manager_initialization + * + * This routine initializes all semaphore manager related data structures. + * + * Input parameters: NONE + * + * Output parameters: NONE + */ + +void _POSIX_Semaphore_Manager_initialization(void) +{ + _Objects_Initialize_information( + &_POSIX_Semaphore_Information, /* object information table */ + OBJECTS_POSIX_API, /* object API */ + OBJECTS_POSIX_SEMAPHORES, /* object class */ + Configuration_POSIX_API.maximum_semaphores, + /* maximum objects of this class */ + sizeof( POSIX_Semaphore_Control ), + /* size of this object's control block */ + true, /* true if names for this object are strings */ + _POSIX_PATH_MAX /* maximum length of each object's name */ +#if defined(RTEMS_MULTIPROCESSING) + , + false, /* true if this is a global object class */ + NULL /* Proxy extraction support callout */ +#endif + ); +} diff --git a/cpukit/posix/src/semaphorecreatesupp.c b/cpukit/posix/src/semaphorecreatesupp.c new file mode 100644 index 0000000000..42e530bf07 --- /dev/null +++ b/cpukit/posix/src/semaphorecreatesupp.c @@ -0,0 +1,113 @@ +/* + * COPYRIGHT (c) 1989-2009. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdarg.h> + +#include <errno.h> +#include <fcntl.h> +#include <pthread.h> +#include <semaphore.h> +#include <limits.h> +#include <string.h> /* strlen */ + +#include <rtems/system.h> +#include <rtems/score/object.h> +#include <rtems/posix/semaphore.h> +#include <rtems/posix/time.h> +#include <rtems/seterr.h> + +/* pure ANSI mode does not have this prototype */ +size_t strnlen(const char *, size_t); + +/* + * _POSIX_Semaphore_Create_support + * + * This routine does the actual creation and initialization of + * a poxix semaphore. It is a support routine for sem_init and + * sem_open. + */ +int _POSIX_Semaphore_Create_support( + const char *name, + int pshared, + unsigned int value, + POSIX_Semaphore_Control **the_sem +) +{ + POSIX_Semaphore_Control *the_semaphore; + CORE_semaphore_Attributes *the_sem_attr; + char *name_p = (char *)name; + + /* Sharing semaphores among processes is not currently supported */ + if (pshared != 0) + rtems_set_errno_and_return_minus_one( ENOSYS ); + + if ( name ) { + if ( strnlen( name, NAME_MAX ) >= NAME_MAX ) + rtems_set_errno_and_return_minus_one( ENAMETOOLONG ); + } + + _Thread_Disable_dispatch(); + + the_semaphore = _POSIX_Semaphore_Allocate(); + + if ( !the_semaphore ) { + _Thread_Enable_dispatch(); + rtems_set_errno_and_return_minus_one( ENOSPC ); + } + + the_semaphore->process_shared = pshared; + + if ( name ) { + the_semaphore->named = true; + the_semaphore->open_count = 1; + the_semaphore->linked = true; + } else { + the_semaphore->named = false; + the_semaphore->open_count = 0; + the_semaphore->linked = false; + } + + the_sem_attr = &the_semaphore->Semaphore.Attributes; + + /* + * POSIX does not appear to specify what the discipline for + * blocking tasks on this semaphore should be. It could somehow + * be derived from the current scheduling policy. One + * thing is certain, no matter what we decide, it won't be + * the same as all other POSIX implementations. :) + */ + the_sem_attr->discipline = CORE_SEMAPHORE_DISCIPLINES_FIFO; + + /* + * This effectively disables limit checking. + */ + the_sem_attr->maximum_count = 0xFFFFFFFF; + + _CORE_semaphore_Initialize( &the_semaphore->Semaphore, the_sem_attr, value ); + + /* + * Make the semaphore available for use. + */ + _Objects_Open_string( + &_POSIX_Semaphore_Information, + &the_semaphore->Object, + name_p + ); + + *the_sem = the_semaphore; + + _Thread_Enable_dispatch(); + return 0; +} diff --git a/cpukit/posix/src/semaphoredeletesupp.c b/cpukit/posix/src/semaphoredeletesupp.c new file mode 100644 index 0000000000..b9b8408c76 --- /dev/null +++ b/cpukit/posix/src/semaphoredeletesupp.c @@ -0,0 +1,50 @@ +/* + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdarg.h> + +#include <errno.h> +#include <fcntl.h> +#include <pthread.h> +#include <semaphore.h> +#include <limits.h> + +#include <rtems/system.h> +#include <rtems/score/object.h> +#include <rtems/posix/semaphore.h> +#include <rtems/posix/time.h> +#include <rtems/seterr.h> + +/*PAGE + * + * _POSIX_Semaphore_Delete + */ + +void _POSIX_Semaphore_Delete( + POSIX_Semaphore_Control *the_semaphore +) +{ + if ( !the_semaphore->linked && !the_semaphore->open_count ) { + _Objects_Close( &_POSIX_Semaphore_Information, &the_semaphore->Object ); + + _CORE_semaphore_Flush( + &the_semaphore->Semaphore, + NULL, + -1 + ); + + _POSIX_Semaphore_Free( the_semaphore ); + } +} diff --git a/cpukit/posix/src/semaphorenametoid.c b/cpukit/posix/src/semaphorenametoid.c new file mode 100644 index 0000000000..e550910653 --- /dev/null +++ b/cpukit/posix/src/semaphorenametoid.c @@ -0,0 +1,63 @@ +/* + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdarg.h> + +#include <errno.h> +#include <fcntl.h> +#include <pthread.h> +#include <semaphore.h> +#include <limits.h> + +#include <rtems/system.h> +#include <rtems/score/object.h> +#include <rtems/posix/semaphore.h> +#include <rtems/posix/time.h> +#include <rtems/seterr.h> + +/*PAGE + * + * _POSIX_Semaphore_Name_to_id + * + * Look up the specified name and attempt to locate the id + * for the associated semaphore. + */ + +int _POSIX_Semaphore_Name_to_id( + const char *name, + sem_t *id +) +{ + Objects_Name_or_id_lookup_errors status; + Objects_Id the_id; + + if ( !name ) + return EINVAL; + + if ( !name[0] ) + return EINVAL; + + status = _Objects_Name_to_id_string( + &_POSIX_Semaphore_Information, + name, + &the_id + ); + *id = the_id; + + if ( status == OBJECTS_NAME_OR_ID_LOOKUP_SUCCESSFUL ) + return 0; + + return ENOENT; +} diff --git a/cpukit/posix/src/semaphoretranslatereturncode.c b/cpukit/posix/src/semaphoretranslatereturncode.c new file mode 100644 index 0000000000..c87f5c93c8 --- /dev/null +++ b/cpukit/posix/src/semaphoretranslatereturncode.c @@ -0,0 +1,59 @@ +/* + * POSIX Semaphore Error Translation + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/score/coresem.h> + +/* + * _POSIX_Semaphore_Translate_core_semaphore_return_code + * + * Input parameters: + * the_semaphore_status - semaphore status code to translate + * + * Output parameters: + * status code - translated POSIX status code + * + */ + +static int _POSIX_Semaphore_Return_codes[CORE_SEMAPHORE_STATUS_LAST + 1] = { + 0, /* CORE_SEMAPHORE_STATUS_SUCCESSFUL */ + EAGAIN, /* CORE_SEMAPHORE_STATUS_UNSATISFIED_NOWAIT */ + EAGAIN, /* CORE_SEMAPHORE_WAS_DELETED */ + ETIMEDOUT, /* CORE_SEMAPHORE_TIMEOUT */ + /* The next error can not occur since we set the maximum + * count to the largest value the count can hold. + */ + ENOSYS, /* CORE_SEMAPHORE_MAXIMUM_COUNT_EXCEEDED */ +}; + + +int _POSIX_Semaphore_Translate_core_semaphore_return_code( + CORE_semaphore_Status the_semaphore_status +) +{ + /* + * Internal consistency check for bad status from SuperCore + */ + #if defined(RTEMS_DEBUG) + if ( the_semaphore_status > CORE_SEMAPHORE_STATUS_LAST ) + return EINVAL; + #endif + return _POSIX_Semaphore_Return_codes[the_semaphore_status]; +} diff --git a/cpukit/posix/src/semaphorewaitsupp.c b/cpukit/posix/src/semaphorewaitsupp.c new file mode 100644 index 0000000000..76e7edc4bc --- /dev/null +++ b/cpukit/posix/src/semaphorewaitsupp.c @@ -0,0 +1,73 @@ +/* + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdarg.h> + +#include <errno.h> +#include <fcntl.h> +#include <pthread.h> +#include <semaphore.h> +#include <limits.h> + +#include <rtems/system.h> +#include <rtems/score/object.h> +#include <rtems/posix/semaphore.h> +#include <rtems/posix/time.h> +#include <rtems/seterr.h> + +/*PAGE + * + * _POSIX_Semaphore_Wait_support + */ + +int _POSIX_Semaphore_Wait_support( + sem_t *sem, + bool blocking, + Watchdog_Interval timeout +) +{ + POSIX_Semaphore_Control *the_semaphore; + Objects_Locations location; + + the_semaphore = _POSIX_Semaphore_Get( sem, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + _CORE_semaphore_Seize( + &the_semaphore->Semaphore, + the_semaphore->Object.id, + blocking, + timeout + ); + _Thread_Enable_dispatch(); + + if ( !_Thread_Executing->Wait.return_code ) + return 0; + + rtems_set_errno_and_return_minus_one( + _POSIX_Semaphore_Translate_core_semaphore_return_code( + _Thread_Executing->Wait.return_code + ) + ); + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: +#endif + case OBJECTS_ERROR: + break; + } + + rtems_set_errno_and_return_minus_one( EINVAL ); +} diff --git a/cpukit/posix/src/semclose.c b/cpukit/posix/src/semclose.c new file mode 100644 index 0000000000..c265c867d5 --- /dev/null +++ b/cpukit/posix/src/semclose.c @@ -0,0 +1,64 @@ +/* + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdarg.h> + +#include <errno.h> +#include <fcntl.h> +#include <pthread.h> +#include <semaphore.h> +#include <limits.h> + +#include <rtems/system.h> +#include <rtems/score/object.h> +#include <rtems/posix/semaphore.h> +#include <rtems/posix/time.h> +#include <rtems/seterr.h> + + +/*PAGE + * + * sem_close + * + * Routine to close a semaphore that has been opened or initialized. + * + * 11.2.4 Close a Named Semaphore, P1003.1b-1993, p.224 + */ + +int sem_close( + sem_t *sem +) +{ + register POSIX_Semaphore_Control *the_semaphore; + Objects_Locations location; + + the_semaphore = _POSIX_Semaphore_Get( sem, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + the_semaphore->open_count -= 1; + _POSIX_Semaphore_Delete( the_semaphore ); + _Thread_Enable_dispatch(); + return 0; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: +#endif + case OBJECTS_ERROR: + break; + } + + rtems_set_errno_and_return_minus_one( EINVAL ); +} diff --git a/cpukit/posix/src/semdestroy.c b/cpukit/posix/src/semdestroy.c new file mode 100644 index 0000000000..8a3b20c23f --- /dev/null +++ b/cpukit/posix/src/semdestroy.c @@ -0,0 +1,67 @@ +/* + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdarg.h> + +#include <errno.h> +#include <fcntl.h> +#include <pthread.h> +#include <semaphore.h> +#include <limits.h> + +#include <rtems/system.h> +#include <rtems/score/object.h> +#include <rtems/posix/semaphore.h> +#include <rtems/posix/time.h> +#include <rtems/seterr.h> + +/*PAGE + * + * 11.2.2 Destroy an Unnamed Semaphore, P1003.1b-1993, p.220 + */ + +int sem_destroy( + sem_t *sem +) +{ + register POSIX_Semaphore_Control *the_semaphore; + Objects_Locations location; + + the_semaphore = _POSIX_Semaphore_Get( sem, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + /* + * Undefined operation on a named semaphore. + */ + + if ( the_semaphore->named == true ) { + _Thread_Enable_dispatch(); + rtems_set_errno_and_return_minus_one( EINVAL ); + } + + _POSIX_Semaphore_Delete( the_semaphore ); + _Thread_Enable_dispatch(); + return 0; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: +#endif + case OBJECTS_ERROR: + break; + } + + rtems_set_errno_and_return_minus_one( EINVAL ); +} diff --git a/cpukit/posix/src/semgetvalue.c b/cpukit/posix/src/semgetvalue.c new file mode 100644 index 0000000000..81042bf316 --- /dev/null +++ b/cpukit/posix/src/semgetvalue.c @@ -0,0 +1,59 @@ +/* + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdarg.h> + +#include <errno.h> +#include <fcntl.h> +#include <pthread.h> +#include <semaphore.h> +#include <limits.h> + +#include <rtems/system.h> +#include <rtems/score/object.h> +#include <rtems/posix/semaphore.h> +#include <rtems/posix/time.h> +#include <rtems/seterr.h> + +/*PAGE + * + * 11.2.8 Get the Value of a Semaphore, P1003.1b-1993, p.229 + */ + +int sem_getvalue( + sem_t *sem, + int *sval +) +{ + register POSIX_Semaphore_Control *the_semaphore; + Objects_Locations location; + + the_semaphore = _POSIX_Semaphore_Get( sem, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + *sval = _CORE_semaphore_Get_count( &the_semaphore->Semaphore ); + _Thread_Enable_dispatch(); + return 0; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: +#endif + case OBJECTS_ERROR: + break; + } + + rtems_set_errno_and_return_minus_one( EINVAL ); +} diff --git a/cpukit/posix/src/seminit.c b/cpukit/posix/src/seminit.c new file mode 100644 index 0000000000..132be509e7 --- /dev/null +++ b/cpukit/posix/src/seminit.c @@ -0,0 +1,58 @@ +/* + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdarg.h> + +#include <errno.h> +#include <fcntl.h> +#include <pthread.h> +#include <semaphore.h> +#include <limits.h> + +#include <rtems/system.h> +#include <rtems/score/object.h> +#include <rtems/posix/semaphore.h> +#include <rtems/posix/time.h> +#include <rtems/seterr.h> + +/*PAGE + * + * 11.2.1 Initialize an Unnamed Semaphore, P1003.1b-1993, p.219 + */ + +int sem_init( + sem_t *sem, + int pshared, + unsigned int value +) +{ + int status; + POSIX_Semaphore_Control *the_semaphore; + + if ( !sem ) + rtems_set_errno_and_return_minus_one( EINVAL ); + + status = _POSIX_Semaphore_Create_support( + NULL, + pshared, + value, + &the_semaphore + ); + + if ( status != -1 ) + *sem = the_semaphore->Object.id; + + return status; +} diff --git a/cpukit/posix/src/semopen.c b/cpukit/posix/src/semopen.c new file mode 100644 index 0000000000..b51d2043be --- /dev/null +++ b/cpukit/posix/src/semopen.c @@ -0,0 +1,136 @@ +/* + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdarg.h> + +#include <errno.h> +#include <fcntl.h> +#include <pthread.h> +#include <semaphore.h> +#include <limits.h> + +#include <rtems/system.h> +#include <rtems/score/object.h> +#include <rtems/posix/semaphore.h> +#include <rtems/posix/time.h> +#include <rtems/seterr.h> + +/*PAGE + * + * sem_open + * + * Opens a named semaphore. Used in conjunction with the sem_close + * and sem_unlink commands. + * + * 11.2.3 Initialize/Open a Named Semaphore, P1003.1b-1993, p.221 + * + * NOTE: When oflag is O_CREAT, then optional third and fourth + * parameters must be present. + */ + +sem_t *sem_open( + const char *name, + int oflag, + ... + /* mode_t mode, */ + /* unsigned int value */ +) +{ + va_list arg; + mode_t mode; + unsigned int value = 0; + int status; + sem_t the_semaphore_id; + sem_t *id; + POSIX_Semaphore_Control *the_semaphore; + Objects_Locations location; + + _Thread_Disable_dispatch(); + + if ( oflag & O_CREAT ) { + va_start(arg, oflag); + mode = (mode_t) va_arg( arg, unsigned int ); + value = va_arg( arg, unsigned int ); + va_end(arg); + } + + status = _POSIX_Semaphore_Name_to_id( name, &the_semaphore_id ); + + /* + * If the name to id translation worked, then the semaphore exists + * and we can just return a pointer to the id. Otherwise we may + * need to check to see if this is a "semaphore does not exist" + * or some other miscellaneous error on the name. + */ + + if ( status ) { + + /* + * Unless provided a valid name that did not already exist + * and we are willing to create then it is an error. + */ + + if ( !( status == ENOENT && (oflag & O_CREAT) ) ) { + _Thread_Enable_dispatch(); + rtems_set_errno_and_return_minus_one_cast( status, sem_t * ); + } + } else { + + /* + * Check for existence with creation. + */ + + if ( (oflag & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL) ) { + _Thread_Enable_dispatch(); + rtems_set_errno_and_return_minus_one_cast( EEXIST, sem_t * ); + } + + the_semaphore = _POSIX_Semaphore_Get( &the_semaphore_id, &location ); + the_semaphore->open_count += 1; + _Thread_Enable_dispatch(); + _Thread_Enable_dispatch(); + goto return_id; + } + + /* + * At this point, the semaphore does not exist and everything has been + * checked. We should go ahead and create a semaphore. + */ + + status =_POSIX_Semaphore_Create_support( + name, + false, /* not shared across processes */ + value, + &the_semaphore + ); + + /* + * errno was set by Create_support, so don't set it again. + */ + + _Thread_Enable_dispatch(); + + if ( status == -1 ) + return SEM_FAILED; + +return_id: + #if defined(RTEMS_USE_16_BIT_OBJECT) + the_semaphore->Semaphore_id = the_semaphore->Object.id; + id = &the_semaphore->Semaphore_id; + #else + id = (sem_t *)&the_semaphore->Object.id; + #endif + return id; +} diff --git a/cpukit/posix/src/sempost.c b/cpukit/posix/src/sempost.c new file mode 100644 index 0000000000..785ad3d966 --- /dev/null +++ b/cpukit/posix/src/sempost.c @@ -0,0 +1,66 @@ +/* + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdarg.h> + +#include <errno.h> +#include <fcntl.h> +#include <pthread.h> +#include <semaphore.h> +#include <limits.h> + +#include <rtems/system.h> +#include <rtems/score/object.h> +#include <rtems/posix/semaphore.h> +#include <rtems/posix/time.h> +#include <rtems/seterr.h> + +/*PAGE + * + * 11.2.7 Unlock a Semaphore, P1003.1b-1993, p.227 + */ + +int sem_post( + sem_t *sem +) +{ + register POSIX_Semaphore_Control *the_semaphore; + Objects_Locations location; + + the_semaphore = _POSIX_Semaphore_Get( sem, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + _CORE_semaphore_Surrender( + &the_semaphore->Semaphore, + the_semaphore->Object.id, +#if defined(RTEMS_MULTIPROCESSING) + NULL /* XXX need to define a routine to handle this case */ +#else + NULL +#endif + ); + _Thread_Enable_dispatch(); + return 0; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: +#endif + case OBJECTS_ERROR: + break; + } + + rtems_set_errno_and_return_minus_one( EINVAL ); +} diff --git a/cpukit/posix/src/semtimedwait.c b/cpukit/posix/src/semtimedwait.c new file mode 100644 index 0000000000..60faafc242 --- /dev/null +++ b/cpukit/posix/src/semtimedwait.c @@ -0,0 +1,81 @@ +/* + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdarg.h> + +#include <errno.h> +#include <fcntl.h> +#include <pthread.h> +#include <semaphore.h> +#include <limits.h> + +#include <rtems/system.h> +#include <rtems/score/object.h> +#include <rtems/posix/semaphore.h> +#include <rtems/posix/time.h> +#include <rtems/seterr.h> + +/*PAGE + * + * 11.2.6 Lock a Semaphore, P1003.1b-1993, p.226 + * + * NOTE: P1003.4b/D8 adds sem_timedwait(), p. 27 + */ + +int sem_timedwait( + sem_t *sem, + const struct timespec *abstime +) +{ + Watchdog_Interval ticks; + bool do_wait = true; + POSIX_Absolute_timeout_conversion_results_t status; + int lock_status; + + /* + * POSIX requires that blocking calls with timeouts that take + * an absolute timeout must ignore issues with the absolute + * time provided if the operation would otherwise succeed. + * So we check the abstime provided, and hold on to whether it + * is valid or not. If it isn't correct and in the future, + * then we do a polling operation and convert the UNSATISFIED + * status into the appropriate error. + * + * If the status is POSIX_ABSOLUTE_TIMEOUT_INVALID, + * POSIX_ABSOLUTE_TIMEOUT_IS_IN_PAST, or POSIX_ABSOLUTE_TIMEOUT_IS_NOW, + * then we should not wait. + */ + status = _POSIX_Absolute_timeout_to_ticks( abstime, &ticks ); + if ( status != POSIX_ABSOLUTE_TIMEOUT_IS_IN_FUTURE ) + do_wait = false; + + lock_status = _POSIX_Semaphore_Wait_support( sem, do_wait, ticks ); + + /* + * This service only gives us the option to block. We used a polling + * attempt to obtain if the abstime was not in the future. If we did + * not obtain the semaphore, then not look at the status immediately, + * make sure the right reason is returned. + */ + if ( !do_wait && (lock_status == EBUSY) ) { + if ( lock_status == POSIX_ABSOLUTE_TIMEOUT_INVALID ) + rtems_set_errno_and_return_minus_one( EINVAL ); + if ( lock_status == POSIX_ABSOLUTE_TIMEOUT_IS_IN_PAST || + lock_status == POSIX_ABSOLUTE_TIMEOUT_IS_NOW ) + rtems_set_errno_and_return_minus_one( ETIMEDOUT ); + } + + return lock_status; +} diff --git a/cpukit/posix/src/semtrywait.c b/cpukit/posix/src/semtrywait.c new file mode 100644 index 0000000000..fdf50be29d --- /dev/null +++ b/cpukit/posix/src/semtrywait.c @@ -0,0 +1,42 @@ +/* + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdarg.h> + +#include <errno.h> +#include <fcntl.h> +#include <pthread.h> +#include <semaphore.h> +#include <limits.h> + +#include <rtems/system.h> +#include <rtems/score/object.h> +#include <rtems/posix/semaphore.h> +#include <rtems/posix/time.h> +#include <rtems/seterr.h> + +/*PAGE + * + * 11.2.6 Lock a Semaphore, P1003.1b-1993, p.226 + * + * NOTE: P1003.4b/D8 adds sem_timedwait(), p. 27 + */ + +int sem_trywait( + sem_t *sem +) +{ + return _POSIX_Semaphore_Wait_support(sem, false, THREAD_QUEUE_WAIT_FOREVER); +} diff --git a/cpukit/posix/src/semunlink.c b/cpukit/posix/src/semunlink.c new file mode 100644 index 0000000000..864749c6ac --- /dev/null +++ b/cpukit/posix/src/semunlink.c @@ -0,0 +1,67 @@ +/* + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdarg.h> + +#include <errno.h> +#include <fcntl.h> +#include <pthread.h> +#include <semaphore.h> +#include <limits.h> + +#include <rtems/system.h> +#include <rtems/score/object.h> +#include <rtems/posix/semaphore.h> +#include <rtems/posix/time.h> +#include <rtems/seterr.h> + +/*PAGE + * + * sem_unlink + * + * Unlinks a named semaphore, sem_close must also be called to remove + * the semaphore. + * + * 11.2.5 Remove a Named Semaphore, P1003.1b-1993, p.225 + */ + +int sem_unlink( + const char *name +) +{ + int status; + register POSIX_Semaphore_Control *the_semaphore; + sem_t the_semaphore_id; + + _Thread_Disable_dispatch(); + + status = _POSIX_Semaphore_Name_to_id( name, &the_semaphore_id ); + if ( status != 0 ) { + _Thread_Enable_dispatch(); + rtems_set_errno_and_return_minus_one( status ); + } + + the_semaphore = (POSIX_Semaphore_Control *) _Objects_Get_local_object( + &_POSIX_Semaphore_Information, + _Objects_Get_index( the_semaphore_id ) + ); + + the_semaphore->linked = false; + _POSIX_Semaphore_Namespace_remove( the_semaphore ); + _POSIX_Semaphore_Delete( the_semaphore ); + + _Thread_Enable_dispatch(); + return 0; +} diff --git a/cpukit/posix/src/semwait.c b/cpukit/posix/src/semwait.c new file mode 100644 index 0000000000..462c31ccda --- /dev/null +++ b/cpukit/posix/src/semwait.c @@ -0,0 +1,42 @@ +/* + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdarg.h> + +#include <errno.h> +#include <fcntl.h> +#include <pthread.h> +#include <semaphore.h> +#include <limits.h> + +#include <rtems/system.h> +#include <rtems/score/object.h> +#include <rtems/posix/semaphore.h> +#include <rtems/posix/time.h> +#include <rtems/seterr.h> + +/*PAGE + * + * 11.2.6 Lock a Semaphore, P1003.1b-1993, p.226 + * + * NOTE: P1003.4b/D8 adds sem_timedwait(), p. 27 + */ + +int sem_wait( + sem_t *sem +) +{ + return _POSIX_Semaphore_Wait_support( sem, true, THREAD_QUEUE_WAIT_FOREVER ); +} diff --git a/cpukit/posix/src/setcancelstate.c b/cpukit/posix/src/setcancelstate.c new file mode 100644 index 0000000000..7b7543b639 --- /dev/null +++ b/cpukit/posix/src/setcancelstate.c @@ -0,0 +1,66 @@ +/* + * COPYRIGHT (c) 1989-2009. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/score/chain.h> +#include <rtems/score/isr.h> +#include <rtems/score/thread.h> +#include <rtems/posix/cancel.h> +#include <rtems/posix/pthread.h> +#include <rtems/posix/threadsup.h> + +/* + * 18.2.2 Setting Cancelability State, P1003.1c/Draft 10, p. 183 + */ + +int pthread_setcancelstate( + int state, + int *oldstate +) +{ + POSIX_API_Control *thread_support; + + /* + * Don't even think about deleting a resource from an ISR. + * Besides this request is supposed to be for _Thread_Executing + * and the ISR context is not a thread. + */ + + if ( _ISR_Is_in_progress() ) + return EPROTO; + + if ( !oldstate ) + return EINVAL; + + if ( state != PTHREAD_CANCEL_ENABLE && state != PTHREAD_CANCEL_DISABLE ) + return EINVAL; + + thread_support = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ]; + + _Thread_Disable_dispatch(); + *oldstate = thread_support->cancelability_state; + thread_support->cancelability_state = state; + + _POSIX_Thread_Evaluate_cancellation_and_enable_dispatch(_Thread_Executing); + + /* + * _Thread_Enable_dispatch is invoked by above call. + */ + + return 0; +} diff --git a/cpukit/posix/src/setcanceltype.c b/cpukit/posix/src/setcanceltype.c new file mode 100644 index 0000000000..85f645bad4 --- /dev/null +++ b/cpukit/posix/src/setcanceltype.c @@ -0,0 +1,65 @@ +/* + * COPYRIGHT (c) 1989-2009. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/score/chain.h> +#include <rtems/score/isr.h> +#include <rtems/score/thread.h> +#include <rtems/posix/cancel.h> +#include <rtems/posix/pthread.h> +#include <rtems/posix/threadsup.h> + +/* + * 18.2.2 Setting Cancelability State, P1003.1c/Draft 10, p. 183 + */ + +int pthread_setcanceltype( + int type, + int *oldtype +) +{ + POSIX_API_Control *thread_support; + + /* + * Don't even think about deleting a resource from an ISR. + * Besides this request is supposed to be for _Thread_Executing + * and the ISR context is not a thread. + */ + + if ( _ISR_Is_in_progress() ) + return EPROTO; + + if ( !oldtype ) + return EINVAL; + + if ( type != PTHREAD_CANCEL_DEFERRED && type != PTHREAD_CANCEL_ASYNCHRONOUS ) + return EINVAL; + + thread_support = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ]; + + _Thread_Disable_dispatch(); + *oldtype = thread_support->cancelability_type; + thread_support->cancelability_type = type; + + _POSIX_Thread_Evaluate_cancellation_and_enable_dispatch(_Thread_Executing); + + /* + * _Thread_Enable_dispatch is invoked by above call. + */ + return 0; +} diff --git a/cpukit/posix/src/setitimer.c b/cpukit/posix/src/setitimer.c new file mode 100644 index 0000000000..24a4723100 --- /dev/null +++ b/cpukit/posix/src/setitimer.c @@ -0,0 +1,43 @@ +/* + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <time.h> +#include <sys/time.h> +#include <errno.h> +#include <rtems/seterr.h> + +int setitimer( + int which, + const struct itimerval *value, + struct itimerval *ovalue +) +{ + if ( !value ) + rtems_set_errno_and_return_minus_one( EFAULT ); + + if ( !ovalue ) + rtems_set_errno_and_return_minus_one( EFAULT ); + + switch ( which ) { + case ITIMER_REAL: + case ITIMER_VIRTUAL: + case ITIMER_PROF: + rtems_set_errno_and_return_minus_one( ENOSYS ); + default: + break; + } + rtems_set_errno_and_return_minus_one( EINVAL ); +} + diff --git a/cpukit/posix/src/sigaction.c b/cpukit/posix/src/sigaction.c new file mode 100644 index 0000000000..b92154663c --- /dev/null +++ b/cpukit/posix/src/sigaction.c @@ -0,0 +1,93 @@ +/* + * 3.3.4 Examine and Change Signal Action, P1003.1b-1993, p. 70 + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <signal.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/pthread.h> +#include <rtems/posix/psignal.h> +#include <rtems/seterr.h> +#include <rtems/score/isr.h> + +/* + * PARAMETERS_PASSING_S is defined in ptimer.c + */ + +extern void PARAMETERS_PASSING_S (int num_signal, const struct sigaction inf); + +int sigaction( + int sig, + const struct sigaction *act, + struct sigaction *oact +) +{ + ISR_Level level; + + if ( oact ) + *oact = _POSIX_signals_Vectors[ sig ]; + + if ( !sig ) + rtems_set_errno_and_return_minus_one( EINVAL ); + + if ( !is_valid_signo(sig) ) + rtems_set_errno_and_return_minus_one( EINVAL ); + + /* + * Some signals cannot be ignored (P1003.1b-1993, pp. 70-72 and references. + * + * NOTE: Solaris documentation claims to "silently enforce" this which + * contradicts the POSIX specification. + */ + + if ( sig == SIGKILL ) + rtems_set_errno_and_return_minus_one( EINVAL ); + + /* + * Evaluate the new action structure and set the global signal vector + * appropriately. + */ + + if ( act ) { + + /* + * Unless the user is installing the default signal actions, then + * we can just copy the provided sigaction structure into the vectors. + */ + + _ISR_Disable( level ); + if ( act->sa_handler == SIG_DFL ) { + _POSIX_signals_Vectors[ sig ] = _POSIX_signals_Default_vectors[ sig ]; + } else { + _POSIX_signals_Clear_process_signals( sig ); + _POSIX_signals_Vectors[ sig ] = *act; + } + _ISR_Enable( level ); + } + + /* + * No need to evaluate or dispatch because: + * + * + If we were ignoring the signal before, none could be pending + * now (signals not posted when SIG_IGN). + * + If we are now ignoring a signal that was previously pending, + * we clear the pending signal indicator. + */ + + return 0; +} diff --git a/cpukit/posix/src/sigaddset.c b/cpukit/posix/src/sigaddset.c new file mode 100644 index 0000000000..5c65ab60eb --- /dev/null +++ b/cpukit/posix/src/sigaddset.c @@ -0,0 +1,40 @@ +/* + * 3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69 + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/sigset.h> +#include <rtems/seterr.h> + +int sigaddset( + sigset_t *set, + int signo +) +{ + if ( !set ) + rtems_set_errno_and_return_minus_one( EINVAL ); + + if ( !signo ) + rtems_set_errno_and_return_minus_one( EINVAL ); + + if ( !is_valid_signo(signo) ) + rtems_set_errno_and_return_minus_one( EINVAL ); + + *set |= signo_to_mask(signo); + return 0; +} diff --git a/cpukit/posix/src/sigdelset.c b/cpukit/posix/src/sigdelset.c new file mode 100644 index 0000000000..856eb384df --- /dev/null +++ b/cpukit/posix/src/sigdelset.c @@ -0,0 +1,44 @@ +/* + * 3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69 + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/sigset.h> +#include <rtems/seterr.h> + +/* + * 3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69 + */ + +int sigdelset( + sigset_t *set, + int signo +) +{ + if ( !set ) + rtems_set_errno_and_return_minus_one( EINVAL ); + + if ( !signo ) + return 0; + + if ( !is_valid_signo(signo) ) + rtems_set_errno_and_return_minus_one( EINVAL ); + + *set &= ~signo_to_mask(signo); + return 0; +} diff --git a/cpukit/posix/src/sigemptyset.c b/cpukit/posix/src/sigemptyset.c new file mode 100644 index 0000000000..9a6d3580ca --- /dev/null +++ b/cpukit/posix/src/sigemptyset.c @@ -0,0 +1,33 @@ +/* + * 3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69 + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/sigset.h> +#include <rtems/seterr.h> + +int sigemptyset( + sigset_t *set +) +{ + if ( !set ) + rtems_set_errno_and_return_minus_one( EINVAL ); + + *set = 0; + return 0; +} diff --git a/cpukit/posix/src/sigfillset.c b/cpukit/posix/src/sigfillset.c new file mode 100644 index 0000000000..a67b9b9a3e --- /dev/null +++ b/cpukit/posix/src/sigfillset.c @@ -0,0 +1,33 @@ +/* + * 3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69 + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/sigset.h> +#include <rtems/seterr.h> + +int sigfillset( + sigset_t *set +) +{ + if ( !set ) + rtems_set_errno_and_return_minus_one( EINVAL ); + + *set = SIGNAL_ALL_MASK; + return 0; +} diff --git a/cpukit/posix/src/sigismember.c b/cpukit/posix/src/sigismember.c new file mode 100644 index 0000000000..958c5336af --- /dev/null +++ b/cpukit/posix/src/sigismember.c @@ -0,0 +1,42 @@ +/* + * 3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69 + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/sigset.h> +#include <rtems/seterr.h> + +int sigismember( + const sigset_t *set, + int signo +) +{ + if ( !set ) + rtems_set_errno_and_return_minus_one( EINVAL ); + + if ( !signo ) + return 0; + + if ( !is_valid_signo(signo) ) + rtems_set_errno_and_return_minus_one( EINVAL ); + + if ( *set & signo_to_mask(signo) ) + return 1; + + return 0; +} diff --git a/cpukit/posix/src/signal_2.c b/cpukit/posix/src/signal_2.c new file mode 100644 index 0000000000..326861752f --- /dev/null +++ b/cpukit/posix/src/signal_2.c @@ -0,0 +1,54 @@ +/* + * signal(2) - Install signal handler + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <signal.h> +#include <errno.h> + +#ifndef HAVE_SIGHANDLER_T + typedef void (*sighandler_t)(int); +#endif + +sighandler_t signal( + int signum, + sighandler_t handler +) +{ + struct sigaction s; + struct sigaction old; + + s.sa_handler = handler ; + sigemptyset(&s.sa_mask); + + /* + * Depending on which system we want to behave like, one of + * the following versions should be chosen. + */ + +/* #define signal_like_linux */ + +#if defined(signal_like_linux) + s.sa_flags = SA_RESTART | SA_INTERRUPT | SA_NOMASK; + s.sa_restorer= NULL ; +#elif defined(signal_like_SVR4) + s.sa_flags = SA_RESTART; +#else + s.sa_flags = 0; +#endif + + sigaction( signum, &s, &old ); + return (sighandler_t) old.sa_handler; +} diff --git a/cpukit/posix/src/sigpending.c b/cpukit/posix/src/sigpending.c new file mode 100644 index 0000000000..9f22760a58 --- /dev/null +++ b/cpukit/posix/src/sigpending.c @@ -0,0 +1,40 @@ +/* + * 3.3.6 Examine Pending Signals, P1003.1b-1993, p. 75 + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <signal.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/pthread.h> +#include <rtems/posix/psignal.h> +#include <rtems/seterr.h> + +int sigpending( + sigset_t *set +) +{ + POSIX_API_Control *api; + + if ( !set ) + rtems_set_errno_and_return_minus_one( EINVAL ); + + api = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ]; + + *set = api->signals_pending | _POSIX_signals_Pending; + + return 0; +} diff --git a/cpukit/posix/src/sigprocmask.c b/cpukit/posix/src/sigprocmask.c new file mode 100644 index 0000000000..d20a10d1ba --- /dev/null +++ b/cpukit/posix/src/sigprocmask.c @@ -0,0 +1,38 @@ +/* + * 3.3.5 Examine and Change Blocked Signals, P1003.1b-1993, p. 73 + * + * NOTE: P1003.1c/D10, p. 37 adds pthread_sigmask(). + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <signal.h> + +int sigprocmask( + int how, + const sigset_t *set, + sigset_t *oset +) +{ + /* + * P1003.1c/Draft 10, p. 38 maps sigprocmask to pthread_sigmask. + */ + +#if defined(RTEMS_POSIX_API) + return pthread_sigmask( how, set, oset ); +#else + return -1; +#endif +} diff --git a/cpukit/posix/src/sigqueue.c b/cpukit/posix/src/sigqueue.c new file mode 100644 index 0000000000..727f2c6b42 --- /dev/null +++ b/cpukit/posix/src/sigqueue.c @@ -0,0 +1,32 @@ +/* + * 3.3.9 Queue a Signal to a Process, P1003.1b-1993, p. 78 + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/pthread.h> +#include <rtems/posix/psignal.h> + +int sigqueue( + pid_t pid, + int signo, + const union sigval value +) +{ + return killinfo( pid, signo, &value ); +} diff --git a/cpukit/posix/src/sigsuspend.c b/cpukit/posix/src/sigsuspend.c new file mode 100644 index 0000000000..77b6d90a29 --- /dev/null +++ b/cpukit/posix/src/sigsuspend.c @@ -0,0 +1,59 @@ +/* + * 3.3.7 Wait for a Signal, P1003.1b-1993, p. 75 + * + * COPYRIGHT (c) 1989-2004. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <assert.h> +#include <signal.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/pthread.h> +#include <rtems/posix/psignal.h> +#include <rtems/seterr.h> + +int sigsuspend( + const sigset_t *sigmask +) +{ + sigset_t saved_signals_blocked; + sigset_t current_unblocked_signals; + int status; + POSIX_API_Control *api; + + api = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ]; + + /* + * We use SIG_BLOCK and not SIG_SETMASK because there may be + * signals which might be pending, which might get caught here. + * We want the signals to be caught inside sigtimedwait. + */ + status = sigprocmask( SIG_BLOCK, sigmask, &saved_signals_blocked ); + + current_unblocked_signals = ~(*sigmask); + status = sigtimedwait( ¤t_unblocked_signals, NULL, NULL ); + + (void) sigprocmask( SIG_SETMASK, &saved_signals_blocked, NULL ); + + /* + * sigtimedwait() returns the signal number while sigsuspend() + * is supposed to return -1 and EINTR when a signal is caught. + */ + #if defined(RTEMS_DEBUG) + assert( status != -1 ); + #endif + + rtems_set_errno_and_return_minus_one( EINTR ); +} diff --git a/cpukit/posix/src/sigtimedwait.c b/cpukit/posix/src/sigtimedwait.c new file mode 100644 index 0000000000..41ebf88677 --- /dev/null +++ b/cpukit/posix/src/sigtimedwait.c @@ -0,0 +1,177 @@ +/* + * 3.3.8 Synchronously Accept a Signal, P1003.1b-1993, p. 76 + * + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <signal.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/pthread.h> +#include <rtems/posix/psignal.h> +#include <rtems/seterr.h> +#include <rtems/posix/time.h> +#include <rtems/score/isr.h> + +int _POSIX_signals_Get_lowest( + sigset_t set +) +{ + int signo; + + for ( signo = SIGRTMIN ; signo <= SIGRTMAX ; signo++ ) { + if ( set & signo_to_mask( signo ) ) { + goto found_it; + } + } + + /* + * We assume SIGHUP == 1 and is the first non-real-time signal. + */ + + #if (SIGHUP != 1) + #error "Assumption that SIGHUP==1 violated!!" + #endif + for ( signo = SIGHUP ; signo <= __SIGLASTNOTRT ; signo++ ) { + if ( set & signo_to_mask( signo ) ) { + goto found_it; + } + } + + /* + * This is structured this way to eliminate the need to have + * a return 0. This routine will NOT be called unless a signal + * is pending in the set passed in. + */ +found_it: + return signo; +} + +int sigtimedwait( + const sigset_t *set, + siginfo_t *info, + const struct timespec *timeout +) +{ + Thread_Control *the_thread; + POSIX_API_Control *api; + Watchdog_Interval interval; + siginfo_t signal_information; + siginfo_t *the_info; + int signo; + ISR_Level level; + + /* + * Error check parameters before disabling interrupts. + */ + if ( !set ) + rtems_set_errno_and_return_minus_one( EINVAL ); + + /* NOTE: This is very specifically a RELATIVE not ABSOLUTE time + * in the Open Group specification. + */ + + interval = 0; + if ( timeout ) { + + if ( !_Timespec_Is_valid( timeout ) ) + rtems_set_errno_and_return_minus_one( EINVAL ); + + interval = _Timespec_To_ticks( timeout ); + + if ( !interval ) + rtems_set_errno_and_return_minus_one( EINVAL ); + } + + /* + * Initialize local variables. + */ + + the_info = ( info ) ? info : &signal_information; + + the_thread = _Thread_Executing; + + api = the_thread->API_Extensions[ THREAD_API_POSIX ]; + + /* + * What if they are already pending? + */ + + /* API signals pending? */ + + _ISR_Disable( level ); + if ( *set & api->signals_pending ) { + /* XXX real info later */ + the_info->si_signo = _POSIX_signals_Get_lowest( api->signals_pending ); + _POSIX_signals_Clear_signals( + api, + the_info->si_signo, + the_info, + false, + false + ); + _ISR_Enable( level ); + + the_info->si_code = SI_USER; + the_info->si_value.sival_int = 0; + return the_info->si_signo; + } + + /* Process pending signals? */ + + if ( *set & _POSIX_signals_Pending ) { + signo = _POSIX_signals_Get_lowest( _POSIX_signals_Pending ); + _POSIX_signals_Clear_signals( api, signo, the_info, true, false ); + _ISR_Enable( level ); + + the_info->si_signo = signo; + the_info->si_code = SI_USER; + the_info->si_value.sival_int = 0; + return signo; + } + + the_info->si_signo = -1; + + _Thread_Disable_dispatch(); + the_thread->Wait.queue = &_POSIX_signals_Wait_queue; + the_thread->Wait.return_code = EINTR; + the_thread->Wait.option = *set; + the_thread->Wait.return_argument = the_info; + _Thread_queue_Enter_critical_section( &_POSIX_signals_Wait_queue ); + _ISR_Enable( level ); + _Thread_queue_Enqueue( &_POSIX_signals_Wait_queue, interval ); + _Thread_Enable_dispatch(); + + /* + * When the thread is set free by a signal, it is need to eliminate + * the signal. + */ + + _POSIX_signals_Clear_signals( api, the_info->si_signo, the_info, false, false ); + + /* Set errno only if return code is not EINTR or + * if EINTR was caused by a signal being caught, which + * was not in our set. + */ + + if ( (_Thread_Executing->Wait.return_code != EINTR) + || !(*set & signo_to_mask( the_info->si_signo )) ) { + errno = _Thread_Executing->Wait.return_code; + return -1; + } + + return the_info->si_signo; +} diff --git a/cpukit/posix/src/sigwait.c b/cpukit/posix/src/sigwait.c new file mode 100644 index 0000000000..1c34b5ee5b --- /dev/null +++ b/cpukit/posix/src/sigwait.c @@ -0,0 +1,44 @@ +/* + * 3.3.8 Synchronously Accept a Signal, P1003.1b-1993, p. 76 + * + * NOTE: P1003.1c/D10, p. 39 adds sigwait(). + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <signal.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/pthread.h> +#include <rtems/posix/psignal.h> + +int sigwait( + const sigset_t *set, + int *sig +) +{ + int status; + + status = sigtimedwait( set, NULL, NULL ); + + if ( status != -1 ) { + if ( sig ) + *sig = status; + return 0; + } + + return errno; +} diff --git a/cpukit/posix/src/sigwaitinfo.c b/cpukit/posix/src/sigwaitinfo.c new file mode 100644 index 0000000000..2c61e2a8fc --- /dev/null +++ b/cpukit/posix/src/sigwaitinfo.c @@ -0,0 +1,33 @@ +/* + * 3.3.8 Synchronously Accept a Signal, P1003.1b-1993, p. 76 + * + * NOTE: P1003.1c/D10, p. 39 adds sigwait(). + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <signal.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/posix/pthread.h> +#include <rtems/posix/psignal.h> + +int sigwaitinfo( + const sigset_t *set, + siginfo_t *info +) +{ + return sigtimedwait( set, info, NULL ); +} diff --git a/cpukit/posix/src/sysconf.c b/cpukit/posix/src/sysconf.c new file mode 100644 index 0000000000..97a774da25 --- /dev/null +++ b/cpukit/posix/src/sysconf.c @@ -0,0 +1,55 @@ +/* + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <time.h> +#include <unistd.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/seterr.h> +#include <rtems/score/tod.h> +#include <rtems/libio_.h> + +#include <sys/param.h> + +/*PAGE + * + * 4.8.1 Get Configurable System Variables, P1003.1b-1993, p. 95 + */ + +long sysconf( + int name +) +{ + if ( name == _SC_CLK_TCK ) + return (TOD_MICROSECONDS_PER_SECOND / + rtems_configuration_get_microseconds_per_tick()); + + if ( name == _SC_OPEN_MAX ) + return rtems_libio_number_iops; + + if ( name == _SC_GETPW_R_SIZE_MAX ) + return 1024; + + if ( name == _SC_PAGESIZE ) + return PAGE_SIZE; + +#if defined(__sparc__) + if ( name == 515 ) /* Solaris _SC_STACK_PROT */ + return 0; +#endif + + rtems_set_errno_and_return_minus_one( EINVAL ); +} diff --git a/cpukit/posix/src/testcancel.c b/cpukit/posix/src/testcancel.c new file mode 100644 index 0000000000..bea71203d1 --- /dev/null +++ b/cpukit/posix/src/testcancel.c @@ -0,0 +1,57 @@ +/* + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/score/chain.h> +#include <rtems/score/isr.h> +#include <rtems/score/thread.h> +#include <rtems/score/wkspace.h> +#include <rtems/posix/cancel.h> +#include <rtems/posix/pthread.h> +#include <rtems/posix/threadsup.h> + +/*PAGE + * + * 18.2.2 Setting Cancelability State, P1003.1c/Draft 10, p. 183 + */ + +void pthread_testcancel( void ) +{ + POSIX_API_Control *thread_support; + bool cancel = false; + + /* + * Don't even think about deleting a resource from an ISR. + * Besides this request is supposed to be for _Thread_Executing + * and the ISR context is not a thread. + */ + + if ( _ISR_Is_in_progress() ) + return; + + thread_support = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ]; + + _Thread_Disable_dispatch(); + if ( thread_support->cancelability_state == PTHREAD_CANCEL_ENABLE && + thread_support->cancelation_requested ) + cancel = true; + _Thread_Enable_dispatch(); + + if ( cancel ) + _POSIX_Thread_Exit( _Thread_Executing, PTHREAD_CANCELED ); +} diff --git a/cpukit/posix/src/timercreate.c b/cpukit/posix/src/timercreate.c new file mode 100644 index 0000000000..1d843580ba --- /dev/null +++ b/cpukit/posix/src/timercreate.c @@ -0,0 +1,97 @@ +/* + * 14.2.2 Create a Per-Process Timer, P1003.1b-1993, p. 264 + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <time.h> +#include <errno.h> +#include <signal.h> + +#include <rtems/system.h> +#include <rtems/seterr.h> +#include <rtems/score/thread.h> +#include <rtems/posix/psignal.h> +#include <rtems/posix/time.h> +#include <rtems/posix/timer.h> + +int timer_create( + clockid_t clock_id, + struct sigevent *evp, + timer_t *timerid +) +{ + POSIX_Timer_Control *ptimer; + + if ( clock_id != CLOCK_REALTIME ) + rtems_set_errno_and_return_minus_one( EINVAL ); + + if ( !timerid ) + rtems_set_errno_and_return_minus_one( EINVAL ); + + /* + * The data of the structure evp are checked in order to verify if they + * are coherent. + */ + + if (evp != NULL) { + /* The structure has data */ + if ( ( evp->sigev_notify != SIGEV_NONE ) && + ( evp->sigev_notify != SIGEV_SIGNAL ) ) { + /* The value of the field sigev_notify is not valid */ + rtems_set_errno_and_return_minus_one( EINVAL ); + } + + if ( !evp->sigev_signo ) + rtems_set_errno_and_return_minus_one( EINVAL ); + + if ( !is_valid_signo(evp->sigev_signo) ) + rtems_set_errno_and_return_minus_one( EINVAL ); + } + + _Thread_Disable_dispatch(); /* to prevent deletion */ + + /* + * Allocate a timer + */ + ptimer = _POSIX_Timer_Allocate(); + if ( !ptimer ) { + _Thread_Enable_dispatch(); + rtems_set_errno_and_return_minus_one( EAGAIN ); + } + + /* The data of the created timer are stored to use them later */ + + ptimer->state = POSIX_TIMER_STATE_CREATE_NEW; + ptimer->thread_id = _Thread_Executing->Object.id; + + if ( evp != NULL ) { + ptimer->inf.sigev_notify = evp->sigev_notify; + ptimer->inf.sigev_signo = evp->sigev_signo; + ptimer->inf.sigev_value = evp->sigev_value; + } + + ptimer->overrun = 0; + ptimer->timer_data.it_value.tv_sec = 0; + ptimer->timer_data.it_value.tv_nsec = 0; + ptimer->timer_data.it_interval.tv_sec = 0; + ptimer->timer_data.it_interval.tv_nsec = 0; + + _Watchdog_Initialize( &ptimer->Timer, NULL, 0, NULL ); + _Objects_Open_u32(&_POSIX_Timer_Information, &ptimer->Object, 0); + + *timerid = ptimer->Object.id; + _Thread_Enable_dispatch(); + return 0; +} diff --git a/cpukit/posix/src/timerdelete.c b/cpukit/posix/src/timerdelete.c new file mode 100644 index 0000000000..cc70871e3c --- /dev/null +++ b/cpukit/posix/src/timerdelete.c @@ -0,0 +1,63 @@ +/* + * 14.2.3 Delete a Per_process Timer, P1003.1b-1993, p. 266 + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <time.h> +#include <errno.h> +#include <pthread.h> + +#include <rtems/system.h> +#include <rtems/seterr.h> +#include <rtems/score/thread.h> +#include <rtems/posix/time.h> +#include <rtems/posix/timer.h> + + +int timer_delete( + timer_t timerid +) +{ + /* + * IDEA: This function must probably stop the timer first and then delete it + * + * It will have to do a call to rtems_timer_cancel and then another + * call to rtems_timer_delete. + * The call to rtems_timer_delete will be probably unnecessary, + * because rtems_timer_delete stops the timer before deleting it. + */ + POSIX_Timer_Control *ptimer; + Objects_Locations location; + + ptimer = _POSIX_Timer_Get( timerid, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + _Objects_Close( &_POSIX_Timer_Information, &ptimer->Object ); + ptimer->state = POSIX_TIMER_STATE_FREE; + (void) _Watchdog_Remove( &ptimer->Timer ); + _POSIX_Timer_Free( ptimer ); + _Thread_Enable_dispatch(); + return 0; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: +#endif + case OBJECTS_ERROR: + break; + } + + rtems_set_errno_and_return_minus_one( EINVAL ); +} diff --git a/cpukit/posix/src/timergetoverrun.c b/cpukit/posix/src/timergetoverrun.c new file mode 100644 index 0000000000..1ad7bc4d04 --- /dev/null +++ b/cpukit/posix/src/timergetoverrun.c @@ -0,0 +1,58 @@ +/* + * 14.2.4 Per-Process Timers, P1003.1b-1993, p. 267 + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <time.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/seterr.h> +#include <rtems/score/thread.h> +#include <rtems/posix/timer.h> + +/* + * timer_getoverrun + * + * The expiration of a timer must increase by one a counter. + * After the signal handler associated to the timer finishes + * its execution, _POSIX_Timer_TSR will have to set this counter to 0. + */ +int timer_getoverrun( + timer_t timerid +) +{ + int overrun; + POSIX_Timer_Control *ptimer; + Objects_Locations location; + + ptimer = _POSIX_Timer_Get( timerid, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + overrun = ptimer->overrun; + ptimer->overrun = 0; + _Thread_Enable_dispatch(); + return overrun; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: +#endif + case OBJECTS_ERROR: + break; + } + + rtems_set_errno_and_return_minus_one( EINVAL ); +} diff --git a/cpukit/posix/src/timergettime.c b/cpukit/posix/src/timergettime.c new file mode 100644 index 0000000000..bb39121b81 --- /dev/null +++ b/cpukit/posix/src/timergettime.c @@ -0,0 +1,77 @@ +/* + * 14.2.4 Per-Process Timers, P1003.1b-1993, p. 267 + * + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <time.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/seterr.h> +#include <rtems/score/thread.h> +#include <rtems/score/tod.h> +#include <rtems/score/timespec.h> +#include <rtems/posix/timer.h> + +/* + * - When a timer is initialized, the value of the time in + * that moment is stored. + * - When this function is called, it returns the difference + * between the current time and the initialization time. + */ + +int timer_gettime( + timer_t timerid, + struct itimerspec *value +) +{ + POSIX_Timer_Control *ptimer; + Objects_Locations location; + struct timespec current_time; + Watchdog_Interval left; + + if ( !value ) + rtems_set_errno_and_return_minus_one( EINVAL ); + + /* Reads the current time */ + _TOD_Get( ¤t_time ); + + ptimer = _POSIX_Timer_Get( timerid, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + + /* Calculates the time left before the timer finishes */ + + left = + (ptimer->Timer.start_time + ptimer->Timer.initial) - /* expire */ + _Watchdog_Ticks_since_boot; /* now */ + + _Timespec_From_ticks( left, &value->it_value ); + + value->it_interval = ptimer->timer_data.it_interval; + + _Thread_Enable_dispatch(); + return 0; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: +#endif + case OBJECTS_ERROR: + break; + } + + rtems_set_errno_and_return_minus_one( EINVAL ); +} diff --git a/cpukit/posix/src/timerinserthelper.c b/cpukit/posix/src/timerinserthelper.c new file mode 100644 index 0000000000..a2ced7a79b --- /dev/null +++ b/cpukit/posix/src/timerinserthelper.c @@ -0,0 +1,57 @@ +/* + * Helper routine for POSIX timers + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <time.h> + +#include <rtems/system.h> +#include <rtems/seterr.h> +#include <rtems/score/isr.h> +#include <rtems/score/watchdog.h> +#include <rtems/posix/timer.h> +#include <rtems/posix/ptimer.h> + +bool _POSIX_Timer_Insert_helper( + Watchdog_Control *timer, + Watchdog_Interval ticks, + Objects_Id id, + Watchdog_Service_routine_entry TSR, + void *arg +) +{ + ISR_Level level; + + (void) _Watchdog_Remove( timer ); + _ISR_Disable( level ); + + /* + * Check to see if the watchdog has just been inserted by a + * higher priority interrupt. If so, abandon this insert. + */ + if ( timer->state != WATCHDOG_INACTIVE ) { + _ISR_Enable( level ); + return false; + } + + /* + * OK. Now we now the timer was not rescheduled by an interrupt + * so we can atomically initialize it as in use. + */ + _Watchdog_Initialize( timer, TSR, id, arg ); + _Watchdog_Insert_ticks( timer, ticks ); + _ISR_Enable( level ); + return true; +} diff --git a/cpukit/posix/src/timersettime.c b/cpukit/posix/src/timersettime.c new file mode 100644 index 0000000000..d618bd391e --- /dev/null +++ b/cpukit/posix/src/timersettime.c @@ -0,0 +1,136 @@ +/* + * 14.2.4 Per-Process Timers, P1003.1b-1993, p. 267 + * + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <time.h> +#include <errno.h> + +#include <rtems/system.h> +#include <rtems/seterr.h> +#include <rtems/score/thread.h> +#include <rtems/score/tod.h> +#include <rtems/posix/time.h> +#include <rtems/posix/ptimer.h> +#include <rtems/posix/timer.h> + +int timer_settime( + timer_t timerid, + int flags, + const struct itimerspec *value, + struct itimerspec *ovalue +) +{ + POSIX_Timer_Control *ptimer; + Objects_Locations location; + bool activated; + uint32_t initial_period; + struct itimerspec normalize; + + if ( !value ) + rtems_set_errno_and_return_minus_one( EINVAL ); + + /* + * First, it verifies if the structure "value" is correct + * if the number of nanoseconds is not correct return EINVAL + */ + if ( !_Timespec_Is_valid( &(value->it_value) ) ) { + rtems_set_errno_and_return_minus_one( EINVAL ); + } + if ( !_Timespec_Is_valid( &(value->it_interval) ) ) { + rtems_set_errno_and_return_minus_one( EINVAL ); + } + + if ( flags != TIMER_ABSTIME && flags != POSIX_TIMER_RELATIVE ) { + rtems_set_errno_and_return_minus_one( EINVAL ); + } + + normalize = *value; + + /* Convert absolute to relative time */ + if (flags == TIMER_ABSTIME) { + struct timespec now; + _TOD_Get( &now ); + /* Check for seconds in the past */ + if ( _Timespec_Greater_than( &now, &normalize.it_value ) ) + rtems_set_errno_and_return_minus_one( EINVAL ); + _Timespec_Subtract( &now, &normalize.it_value, &normalize.it_value ); + } + + /* If the function reaches this point, then it will be necessary to do + * something with the structure of times of the timer: to stop, start + * or start it again + */ + + ptimer = _POSIX_Timer_Get( timerid, &location ); + switch ( location ) { + + case OBJECTS_LOCAL: + /* First, it verifies if the timer must be stopped */ + if ( normalize.it_value.tv_sec == 0 && normalize.it_value.tv_nsec == 0 ) { + /* Stop the timer */ + (void) _Watchdog_Remove( &ptimer->Timer ); + /* The old data of the timer are returned */ + if ( ovalue ) + *ovalue = ptimer->timer_data; + /* The new data are set */ + ptimer->timer_data = normalize; + /* Indicates that the timer is created and stopped */ + ptimer->state = POSIX_TIMER_STATE_CREATE_STOP; + /* Returns with success */ + _Thread_Enable_dispatch(); + return 0; + } + + /* Convert from seconds and nanoseconds to ticks */ + ptimer->ticks = _Timespec_To_ticks( &value->it_interval ); + initial_period = _Timespec_To_ticks( &normalize.it_value ); + + + activated = _POSIX_Timer_Insert_helper( + &ptimer->Timer, + initial_period, + ptimer->Object.id, + _POSIX_Timer_TSR, + ptimer + ); + if ( !activated ) { + _Thread_Enable_dispatch(); + return 0; + } + + /* + * The timer has been started and is running. So we return the + * old ones in "ovalue" + */ + if ( ovalue ) + *ovalue = ptimer->timer_data; + ptimer->timer_data = normalize; + + /* Indicate that the time is running */ + ptimer->state = POSIX_TIMER_STATE_CREATE_RUN; + _TOD_Get( &ptimer->time ); + _Thread_Enable_dispatch(); + return 0; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: +#endif + case OBJECTS_ERROR: + break; + } + + rtems_set_errno_and_return_minus_one( EINVAL ); +} diff --git a/cpukit/posix/src/timertsr.c b/cpukit/posix/src/timertsr.c new file mode 100644 index 0000000000..b2a86ce4fb --- /dev/null +++ b/cpukit/posix/src/timertsr.c @@ -0,0 +1,81 @@ +/* + * _POSIX_Timer_TSR + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <time.h> +#include <pthread.h> +#include <signal.h> + +#include <rtems/system.h> +#include <rtems/seterr.h> +#include <rtems/score/thread.h> +#include <rtems/score/tod.h> +#include <rtems/posix/time.h> +#include <rtems/posix/ptimer.h> +#include <rtems/posix/timer.h> + +/* + * This is the operation that is run when a timer expires + */ +void _POSIX_Timer_TSR( + Objects_Id timer __attribute__((unused)), + void *data) +{ + POSIX_Timer_Control *ptimer; + bool activated; + + ptimer = (POSIX_Timer_Control *)data; + + /* Increment the number of expirations. */ + ptimer->overrun = ptimer->overrun + 1; + + /* The timer must be reprogrammed */ + if ( ( ptimer->timer_data.it_interval.tv_sec != 0 ) || + ( ptimer->timer_data.it_interval.tv_nsec != 0 ) ) { + activated = _POSIX_Timer_Insert_helper( + &ptimer->Timer, + ptimer->ticks, + ptimer->Object.id, + _POSIX_Timer_TSR, + ptimer + ); + if ( !activated ) + return; + + /* Store the time when the timer was started again */ + _TOD_Get( &ptimer->time ); + + /* The state really did not change but just to be safe */ + ptimer->state = POSIX_TIMER_STATE_CREATE_RUN; + } else { + /* Indicates that the timer is stopped */ + ptimer->state = POSIX_TIMER_STATE_CREATE_STOP; + } + + /* + * The sending of the signal to the process running the handling function + * specified for that signal is simulated + */ + + if ( pthread_kill ( ptimer->thread_id, ptimer->inf.sigev_signo ) ) { + /* XXX error handling */ + } + + /* After the signal handler returns, the count of expirations of the + * timer must be set to 0. + */ + ptimer->overrun = 0; +} diff --git a/cpukit/posix/src/ualarm.c b/cpukit/posix/src/ualarm.c new file mode 100644 index 0000000000..f43aabe52c --- /dev/null +++ b/cpukit/posix/src/ualarm.c @@ -0,0 +1,105 @@ +/* + * 3.4.1 Schedule Alarm, P1003.1b-1993, p. 79 + * + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> +/* #include <errno.h> */ + +#include <rtems/system.h> +#include <rtems/posix/pthread.h> +#include <rtems/posix/psignal.h> +#include <rtems/posix/time.h> + +/*PAGE + * + * _POSIX_signals_Ualarm_TSR + */ + +void _POSIX_signals_Ualarm_TSR( + Objects_Id id __attribute__((unused)), + void *argument __attribute__((unused)) +) +{ + /* + * Send a SIGALRM but if there is a problem, ignore it. + * It's OK, there isn't a way this should fail. + */ + (void) kill( getpid(), SIGALRM ); + + /* + * If the reset interval is non-zero, reschedule ourselves. + */ + _Watchdog_Reset( &_POSIX_signals_Ualarm_timer ); +} + +useconds_t ualarm( + useconds_t useconds, + useconds_t interval +) +{ + useconds_t remaining = 0; + Watchdog_Control *the_timer; + Watchdog_Interval ticks; + struct timespec tp; + + the_timer = &_POSIX_signals_Ualarm_timer; + + /* + * Initialize the timer used to implement alarm(). + */ + + if ( !the_timer->routine ) { + _Watchdog_Initialize( the_timer, _POSIX_signals_Ualarm_TSR, 0, NULL ); + } else { + Watchdog_States state; + + state = _Watchdog_Remove( the_timer ); + if ( (state == WATCHDOG_ACTIVE) || (state == WATCHDOG_REMOVE_IT) ) { + /* + * The stop_time and start_time fields are snapshots of ticks since + * boot. Since alarm() is dealing in seconds, we must account for + * this. + */ + + ticks = the_timer->initial; + ticks -= (the_timer->stop_time - the_timer->start_time); + /* remaining is now in ticks */ + + _Timespec_From_ticks( ticks, &tp ); + remaining = tp.tv_sec * TOD_MICROSECONDS_PER_SECOND; + remaining += tp.tv_nsec / 1000; + } + } + + /* + * If useconds is non-zero, then the caller wants to schedule + * the alarm repeatedly at that interval. If the interval is + * less than a single clock tick, then fudge it to a clock tick. + */ + if ( useconds ) { + Watchdog_Interval ticks; + + tp.tv_sec = useconds / TOD_MICROSECONDS_PER_SECOND; + tp.tv_nsec = (useconds % TOD_MICROSECONDS_PER_SECOND) * 1000; + ticks = _Timespec_To_ticks( &tp ); + if ( ticks == 0 ) + ticks = 1; + + _Watchdog_Insert_ticks( the_timer, _Timespec_To_ticks( &tp ) ); + } + + return remaining; +} diff --git a/cpukit/posix/src/vfork.c b/cpukit/posix/src/vfork.c new file mode 100644 index 0000000000..4db522f015 --- /dev/null +++ b/cpukit/posix/src/vfork.c @@ -0,0 +1,23 @@ +/* + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <sys/types.h> +#include <unistd.h> + +pid_t vfork(void) +{ + return -1; +} + diff --git a/cpukit/posix/src/wait.c b/cpukit/posix/src/wait.c new file mode 100644 index 0000000000..b277930b47 --- /dev/null +++ b/cpukit/posix/src/wait.c @@ -0,0 +1,28 @@ +/* + * waitpid() - POSIX 1003.1b 3.2.1 + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <sys/types.h> +#include <sys/wait.h> +#include <errno.h> +#include <rtems/seterr.h> + +int wait( + int *stat_loc +) +{ + rtems_set_errno_and_return_minus_one( ENOSYS ); +} diff --git a/cpukit/posix/src/waitpid.c b/cpukit/posix/src/waitpid.c new file mode 100644 index 0000000000..b3c3918f4e --- /dev/null +++ b/cpukit/posix/src/waitpid.c @@ -0,0 +1,30 @@ +/* + * waitpid() - POSIX 1003.1 3.2.1 + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <sys/types.h> +#include <sys/wait.h> +#include <errno.h> +#include <rtems/seterr.h> + +int waitpid( + pid_t pid, + int *stat_loc, + int options +) +{ + rtems_set_errno_and_return_minus_one( ENOSYS ); +} |