mirror of
https://github.com/eclipse-threadx/threadx.git
synced 2025-11-16 04:24:48 +00:00
258 lines
9.6 KiB
C
258 lines
9.6 KiB
C
/***************************************************************************
|
|
* Copyright (c) 2024 Microsoft Corporation
|
|
*
|
|
* This program and the accompanying materials are made available under the
|
|
* terms of the MIT License which is available at
|
|
* https://opensource.org/licenses/MIT.
|
|
*
|
|
* SPDX-License-Identifier: MIT
|
|
**************************************************************************/
|
|
|
|
|
|
/**************************************************************************/
|
|
/**************************************************************************/
|
|
/** */
|
|
/** POSIX wrapper for THREADX */
|
|
/** */
|
|
/** */
|
|
/** */
|
|
/**************************************************************************/
|
|
/**************************************************************************/
|
|
|
|
/* Include necessary system files. */
|
|
|
|
#include "tx_api.h" /* Threadx API */
|
|
#include "pthread.h" /* Posix API */
|
|
#include "px_int.h" /* Posix helper functions */
|
|
|
|
|
|
/**************************************************************************/
|
|
/* */
|
|
/* FUNCTION RELEASE */
|
|
/* */
|
|
/* sem_open PORTABLE C */
|
|
/* 6.2.0 */
|
|
/* AUTHOR */
|
|
/* */
|
|
/* William E. Lamie, Microsoft Corporation */
|
|
/* */
|
|
/* DESCRIPTION */
|
|
/* */
|
|
/* This function creates/initialize a semaphore. */
|
|
/* */
|
|
/* INPUT */
|
|
/* */
|
|
/* name Semaphore name */
|
|
/* oflags Flags */
|
|
/* mode Optional parameter */
|
|
/* value Optional parameter */
|
|
/* */
|
|
/* OUTPUT */
|
|
/* */
|
|
/* sem Semaphore descriptor */
|
|
/* */
|
|
/* CALLS */
|
|
/* */
|
|
/* posix_in_thread_context Make sure caller is thread */
|
|
/* posix_find_sem Finds the required semaphore */
|
|
/* posix_get_new_sem Get new semaphore block */
|
|
/* posix_internal_error Internal posix error */
|
|
/* tx_semaphore_create ThreadX semaphore create */
|
|
/* posix_set_sem_name Sets name for semaphore */
|
|
/* */
|
|
/* CALLED BY */
|
|
/* */
|
|
/* Application Code */
|
|
/* */
|
|
/* RELEASE HISTORY */
|
|
/* */
|
|
/* DATE NAME DESCRIPTION */
|
|
/* */
|
|
/* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
|
|
/* 10-31-2022 Scott Larson Update comparison with NULL, */
|
|
/* resulting in version 6.2.0 */
|
|
/* */
|
|
/**************************************************************************/
|
|
sem_t * sem_open(const CHAR * name, ULONG oflag, ...)
|
|
{
|
|
|
|
TX_INTERRUPT_SAVE_AREA
|
|
|
|
TX_SEMAPHORE *TheSem;
|
|
sem_t *semid;
|
|
ULONG retval;
|
|
ULONG len;
|
|
sem_t *posix_sem;
|
|
va_list vl;
|
|
UINT value;
|
|
mode_t mode;
|
|
|
|
/* Make sure we're calling this routine from a thread context. */
|
|
if (!posix_in_thread_context())
|
|
{
|
|
/* return POSIX error. */
|
|
posix_internal_error(444);
|
|
|
|
/* return error. */
|
|
return (( sem_t * )SEM_FAILED);
|
|
}
|
|
|
|
/* Find length of the name. The actual length is not known yet. */
|
|
len = strlen(name);
|
|
|
|
if(len > SEM_NAME_MAX)
|
|
{
|
|
/* Set appropriate errno. */
|
|
posix_errno = ENAMETOOLONG;
|
|
posix_set_pthread_errno(ENAMETOOLONG);
|
|
|
|
/* Return ERROR. */
|
|
return (( sem_t * ) SEM_FAILED);
|
|
}
|
|
|
|
/* Check if semaphore exists. */
|
|
if((semid = posix_find_sem(name)) != NULL)
|
|
{
|
|
if(semid->unlink_flag ==TX_TRUE )
|
|
{
|
|
/* Return error. */
|
|
posix_errno = EINVAL;
|
|
posix_set_pthread_errno(EINVAL);
|
|
return(( sem_t * )SEM_FAILED);
|
|
}
|
|
}
|
|
|
|
/* Semaphore not found. */
|
|
if(!(semid))
|
|
{
|
|
/* Check if flag set is O_EXCL. */
|
|
if( oflag == O_EXCL )
|
|
{
|
|
|
|
/* Set error for sem does not exist and O_CREAT not set. */
|
|
posix_errno = ENOENT;
|
|
posix_set_pthread_errno(ENOENT);
|
|
|
|
/* Return the SEM_FAILED error. */
|
|
return(( sem_t * )SEM_FAILED);
|
|
}
|
|
if( (oflag == O_CREAT) || ( (oflag & (O_CREAT|O_EXCL )) == (O_CREAT|O_EXCL) ) )
|
|
{
|
|
|
|
/* Get the variable arguments pointers. */
|
|
|
|
va_start( vl, oflag );
|
|
|
|
mode = va_arg( vl, mode_t);
|
|
mode = mode; /* just to keep compiler happy */
|
|
|
|
value = va_arg( vl, ULONG);
|
|
|
|
if(value > SEM_VALUE_MAX)
|
|
{
|
|
/* Semaphore value large. */
|
|
posix_errno = EINVAL;
|
|
posix_set_pthread_errno(EINVAL);
|
|
|
|
/* Return ERROR */
|
|
return (( sem_t * )SEM_FAILED);
|
|
|
|
}
|
|
|
|
/* Disable interrupts. */
|
|
TX_DISABLE
|
|
|
|
/* Get a new semaphore from the POSIX semaphore pool. */
|
|
TheSem = posix_get_new_sem();
|
|
|
|
/* Make sure we actually got a semaphore. */
|
|
if (!TheSem)
|
|
{
|
|
/* Semaphore cannot be initialized due to resource constraint. */
|
|
posix_errno = ENOSPC;
|
|
posix_set_pthread_errno(ENOSPC);
|
|
|
|
/* Restore interrupts. */
|
|
TX_RESTORE
|
|
|
|
/* return appropriate error code. */
|
|
return(( sem_t * )SEM_FAILED);
|
|
}
|
|
|
|
/* Set the semaphore name. */
|
|
posix_set_sem_name((sem_t *)TheSem, ( CHAR * ) name);
|
|
|
|
/* Now actually create the ThreadX semaphore. */
|
|
posix_sem = (struct POSIX_SEMAPHORE_STRUCT *)TheSem;
|
|
retval = tx_semaphore_create(TheSem, ( CHAR * ) posix_sem->sem_name , value);
|
|
|
|
/* Make sure it worked. */
|
|
if (retval)
|
|
{
|
|
/* Return generic error. */
|
|
posix_internal_error(100);
|
|
|
|
/* Restore interrupts. */
|
|
TX_RESTORE
|
|
|
|
/* Return appropriate error code. */
|
|
return(( sem_t * )SEM_FAILED);
|
|
}
|
|
|
|
/* Add the calling thread to the thread list. */
|
|
posix_sem -> count += 1;
|
|
|
|
/* Set initial count */
|
|
posix_sem->refCnt = value;
|
|
|
|
/* Give the caller the semaphore ID. */
|
|
semid = (sem_t * )TheSem;
|
|
|
|
/* Restore interrupts. */
|
|
TX_RESTORE
|
|
|
|
/* All done. */
|
|
return(semid);
|
|
}
|
|
|
|
}
|
|
/* Semaphore found. */
|
|
if(semid)
|
|
{
|
|
|
|
/* Check if flags are O_CREAT|O_EXCL. */
|
|
if( (oflag == O_EXCL) || (oflag & (O_CREAT|O_EXCL )) == (O_CREAT|O_EXCL) )
|
|
{
|
|
/* Set appropriate errno. */
|
|
posix_errno = EEXIST;
|
|
posix_set_pthread_errno(EEXIST);
|
|
|
|
/* Return ERROR. */
|
|
return (( sem_t * ) SEM_FAILED);
|
|
}
|
|
|
|
/* Check if flag is only O_CREAT. */
|
|
if( (oflag == O_CREAT) || (oflag==0))
|
|
{
|
|
/* Disable interrupts. */
|
|
TX_DISABLE
|
|
|
|
/* Add the calling thread to the thread list. */
|
|
semid -> count++;
|
|
|
|
/* Restore interrupts. */
|
|
TX_RESTORE
|
|
|
|
/* Return semaphore. */
|
|
return (( sem_t * ) semid);
|
|
}
|
|
}
|
|
|
|
/* Semaphore value large. */
|
|
posix_errno = EINVAL;
|
|
posix_set_pthread_errno(EINVAL);
|
|
|
|
/* Return ERROR. */
|
|
return (( sem_t * ) SEM_FAILED);
|
|
}
|