Files
threadx/utility/rtos_compatibility_layers/posix/px_sem_open.c
Bo Chen (from Dev Box) 8276bcf711 Update copyright.
2024-01-29 13:51:15 +08:00

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);
}