summaryrefslogtreecommitdiffstats
path: root/c/src/exec/posix/src/semaphore.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--c/src/exec/posix/src/semaphore.c575
1 files changed, 575 insertions, 0 deletions
diff --git a/c/src/exec/posix/src/semaphore.c b/c/src/exec/posix/src/semaphore.c
new file mode 100644
index 0000000000..16d44d1894
--- /dev/null
+++ b/c/src/exec/posix/src/semaphore.c
@@ -0,0 +1,575 @@
+/* semaphore.c
+ *
+ */
+
+#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>
+
+/*PAGE
+ *
+ * _POSIX_Semaphore_Manager_initialization
+ *
+ * This routine initializes all semaphore manager related data structures.
+ *
+ * Input parameters:
+ * maximum_semaphores - maximum configured semaphores
+ *
+ * Output parameters: NONE
+ */
+
+void _POSIX_Semaphore_Manager_initialization(
+ unsigned32 maximum_semaphores
+)
+{
+ _Objects_Initialize_information(
+ &_POSIX_Semaphore_Information,
+ OBJECTS_POSIX_SEMAPHORES,
+ TRUE,
+ maximum_semaphores,
+ sizeof( POSIX_Semaphore_Control ),
+ TRUE,
+ _POSIX_PATH_MAX,
+ FALSE
+ );
+}
+
+/*PAGE
+ *
+ * _POSIX_Semaphore_Create_support
+ */
+
+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;
+
+ _Thread_Disable_dispatch();
+
+ the_semaphore = _POSIX_Semaphore_Allocate();
+
+ if ( !the_semaphore ) {
+ _Thread_Enable_dispatch();
+ seterrno( ENOMEM );
+ return -1;
+ }
+
+ if ( pshared == PTHREAD_PROCESS_SHARED &&
+ !( _Objects_MP_Allocate_and_open( &_POSIX_Semaphore_Information, 0,
+ the_semaphore->Object.id, FALSE ) ) ) {
+ _POSIX_Semaphore_Free( the_semaphore );
+ _Thread_Enable_dispatch();
+ seterrno( EAGAIN );
+ return -1;
+ }
+
+ 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_sem_attr = &the_semaphore->Semaphore.Attributes;
+
+ /* XXX
+ *
+ * Note should this be based on the current scheduling policy?
+ */
+
+ the_sem_attr->discipline = CORE_SEMAPHORE_DISCIPLINES_FIFO;
+
+ _CORE_semaphore_Initialize(
+ &the_semaphore->Semaphore,
+ OBJECTS_POSIX_SEMAPHORES,
+ the_sem_attr,
+ value,
+ 0 /* XXX - proxy_extract_callout is unused */
+ );
+
+ /* XXX - need Names to be a string!!! */
+ _Objects_Open(
+ &_POSIX_Semaphore_Information,
+ &the_semaphore->Object,
+ (char *) name
+ );
+
+ *the_sem = the_semaphore;
+
+ if ( pshared == PTHREAD_PROCESS_SHARED )
+ _POSIX_Semaphore_MP_Send_process_packet(
+ POSIX_SEMAPHORE_MP_ANNOUNCE_CREATE,
+ the_semaphore->Object.id,
+ (char *) name,
+ 0 /* proxy id - Not used */
+ );
+
+ _Thread_Enable_dispatch();
+ return 0;
+}
+
+
+/*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;
+
+ status = _POSIX_Semaphore_Create_support(
+ NULL,
+ pshared,
+ value,
+ &the_semaphore
+ );
+
+ if ( status != -1 )
+ *sem = the_semaphore->Object.id;
+
+ return status;
+}
+
+/*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_ERROR:
+ seterrno( EINVAL );
+ return( -1 );
+ case OBJECTS_REMOTE:
+ _Thread_Dispatch();
+ return POSIX_MP_NOT_IMPLEMENTED();
+ seterrno( EINVAL );
+ return( -1 );
+ case OBJECTS_LOCAL:
+ /*
+ * Undefined operation on a named semaphore.
+ */
+
+ if ( the_semaphore->named == TRUE ) {
+ seterrno( EINVAL );
+ return( -1 );
+ }
+
+ _Objects_Close( &_POSIX_Semaphore_Information, &the_semaphore->Object );
+
+ _CORE_semaphore_Flush(
+ &the_semaphore->Semaphore,
+ _POSIX_Semaphore_MP_Send_object_was_deleted,
+ -1 /* XXX should also seterrno -> EINVAL */
+ );
+
+ _POSIX_Semaphore_Free( the_semaphore );
+
+ if ( the_semaphore->process_shared == PTHREAD_PROCESS_SHARED ) {
+
+ _Objects_MP_Close(
+ &_POSIX_Semaphore_Information,
+ the_semaphore->Object.id
+ );
+
+ _POSIX_Semaphore_MP_Send_process_packet(
+ POSIX_SEMAPHORE_MP_ANNOUNCE_DELETE,
+ the_semaphore->Object.id,
+ 0, /* Not used */
+ 0 /* Not used */
+ );
+ }
+ _Thread_Enable_dispatch();
+ return 0;
+ }
+ return POSIX_BOTTOM_REACHED();
+}
+
+/*PAGE
+ *
+ * 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;
+ int status;
+ Objects_Id the_semaphore_id;
+ POSIX_Semaphore_Control *the_semaphore;
+
+
+ if ( oflag & O_CREAT ) {
+ va_start(arg, oflag);
+ mode = (mode_t) va_arg( arg, mode_t * );
+ value = (unsigned int) 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 ) {
+
+ if ( status == EINVAL ) { /* name -> ID translation failed */
+ if ( !(oflag & O_CREAT) ) { /* willing to create it? */
+ seterrno( ENOENT );
+ return (sem_t *) -1;
+ }
+ /* we are willing to create it */
+ }
+ seterrno( status ); /* some type of error */
+ return (sem_t *) -1;
+
+ } else { /* name -> ID translation succeeded */
+
+ if ( (oflag & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL) ) {
+ seterrno( EEXIST );
+ return (sem_t *) -1;
+ }
+
+ /*
+ * XXX In this case we need to do an ID->pointer conversion to
+ * check the mode. This is probably a good place for a subroutine.
+ */
+
+ the_semaphore->open_count += 1;
+
+ return (sem_t *)&the_semaphore->Object.id;
+
+ }
+
+ /* XXX verify this comment...
+ *
+ * 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,
+ TRUE, /* shared across processes */
+ value,
+ &the_semaphore
+ );
+
+ if ( status == -1 )
+ return (sem_t *) -1;
+
+ return (sem_t *) &the_semaphore->Object.id;
+
+}
+
+/*PAGE
+ *
+ * _POSIX_Semaphore_Delete
+ */
+
+void _POSIX_Semaphore_Delete(
+ POSIX_Semaphore_Control *the_semaphore
+)
+{
+ if ( !the_semaphore->linked && !the_semaphore->open_count ) {
+ _POSIX_Semaphore_Free( the_semaphore );
+
+ if ( the_semaphore->process_shared == PTHREAD_PROCESS_SHARED ) {
+
+ _Objects_MP_Close(
+ &_POSIX_Semaphore_Information,
+ the_semaphore->Object.id
+ );
+
+ _POSIX_Semaphore_MP_Send_process_packet(
+ POSIX_SEMAPHORE_MP_ANNOUNCE_DELETE,
+ the_semaphore->Object.id,
+ 0, /* Not used */
+ 0 /* Not used */
+ );
+ }
+
+ }
+}
+
+/*PAGE
+ *
+ * 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_ERROR:
+ seterrno( EINVAL );
+ return( -1 );
+ case OBJECTS_REMOTE:
+ _Thread_Dispatch();
+ return POSIX_MP_NOT_IMPLEMENTED();
+ seterrno( EINVAL );
+ return( -1 );
+ case OBJECTS_LOCAL:
+ the_semaphore->open_count -= 1;
+ _POSIX_Semaphore_Delete( the_semaphore );
+ _Thread_Enable_dispatch();
+ return 0;
+ }
+ return POSIX_BOTTOM_REACHED();
+}
+
+/*PAGE
+ *
+ * 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;
+ Objects_Id the_semaphore_id;
+ Objects_Locations location;
+
+ status = _POSIX_Semaphore_Name_to_id( name, &the_semaphore_id );
+
+ if ( !status ) {
+ seterrno( status );
+ return -1;
+ }
+
+ the_semaphore = _POSIX_Semaphore_Get( &the_semaphore_id, &location );
+ switch ( location ) {
+ case OBJECTS_ERROR:
+ seterrno( EINVAL );
+ return( -1 );
+ case OBJECTS_REMOTE:
+ _Thread_Dispatch();
+ return POSIX_MP_NOT_IMPLEMENTED();
+ seterrno( EINVAL );
+ return( -1 );
+ case OBJECTS_LOCAL:
+
+ if ( the_semaphore->process_shared == PTHREAD_PROCESS_SHARED ) {
+ _Objects_MP_Close(
+ &_POSIX_Semaphore_Information,
+ the_semaphore->Object.id
+ );
+ }
+
+ the_semaphore->linked = FALSE;
+
+ _POSIX_Semaphore_Delete( the_semaphore );
+
+ _Thread_Enable_dispatch();
+ return 0;
+ }
+ return POSIX_BOTTOM_REACHED();
+}
+
+/*PAGE
+ *
+ * _POSIX_Semaphore_Wait_support
+ */
+
+int _POSIX_Semaphore_Wait_support(
+ sem_t *sem,
+ boolean blocking,
+ Watchdog_Interval timeout
+)
+{
+ register POSIX_Semaphore_Control *the_semaphore;
+ Objects_Locations location;
+
+ the_semaphore = _POSIX_Semaphore_Get( sem, &location );
+ switch ( location ) {
+ case OBJECTS_ERROR:
+ seterrno( EINVAL );
+ return( -1 );
+ case OBJECTS_REMOTE:
+ _Thread_Dispatch();
+ return POSIX_MP_NOT_IMPLEMENTED();
+ seterrno( EINVAL );
+ return( -1 );
+ case OBJECTS_LOCAL:
+ _CORE_semaphore_Seize(
+ &the_semaphore->Semaphore,
+ the_semaphore->Object.id,
+ blocking,
+ timeout
+ );
+ _Thread_Enable_dispatch();
+ return _Thread_Executing->Wait.return_code;
+ }
+ return POSIX_BOTTOM_REACHED();
+}
+
+/*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 );
+}
+
+/*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 );
+}
+
+/*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 *timeout
+)
+{
+ return _POSIX_Semaphore_Wait_support(
+ sem,
+ TRUE,
+ _POSIX_Time_Spec_to_interval( timeout )
+ );
+}
+
+/*PAGE
+ *
+ * 11.2.7 Unlock a Semaphore, P1003.1b-1993, p.227
+ */
+
+void POSIX_Semaphore_MP_support(
+ Thread_Control *the_thread,
+ Objects_Id id
+)
+{
+ (void) POSIX_MP_NOT_IMPLEMENTED();
+}
+
+
+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_ERROR:
+ seterrno( EINVAL );
+ return( -1 );
+ case OBJECTS_REMOTE:
+ _Thread_Dispatch();
+ return POSIX_MP_NOT_IMPLEMENTED();
+ seterrno( EINVAL );
+ return( -1 );
+ case OBJECTS_LOCAL:
+ _CORE_semaphore_Surrender(
+ &the_semaphore->Semaphore,
+ the_semaphore->Object.id,
+ POSIX_Semaphore_MP_support
+ );
+ _Thread_Enable_dispatch();
+ return 0;
+ }
+ return POSIX_BOTTOM_REACHED();
+}
+
+/*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_ERROR:
+ seterrno( EINVAL );
+ return( -1 );
+ case OBJECTS_REMOTE:
+ _Thread_Dispatch();
+ return POSIX_MP_NOT_IMPLEMENTED();
+ seterrno( EINVAL );
+ return( -1 );
+ case OBJECTS_LOCAL:
+ *sval = _CORE_semaphore_Get_count( &the_semaphore->Semaphore );
+ _Thread_Enable_dispatch();
+ return 0;
+ }
+ return POSIX_BOTTOM_REACHED();
+}