/////////////////////////////////////////////////////////////////////////////// // // IMPORTANT NOTICE // // The following open source license statement does not apply to any // entity in the Exception List published by FMSoft. // // For more information, please visit: // // https://www.fmsoft.cn/exception-list // ////////////////////////////////////////////////////////////////////////////// /** * \file psos.h * \author Wei Yongming * \date 2007/05/28 * * \brief This header contains the declaration of pSOS+ system calls, the definition * of related structures, and the error codes. * \verbatim This file is part of MiniGUI, a mature cross-platform windowing and Graphics User Interface (GUI) support system for embedded systems and smart IoT devices. Copyright (C) 2008~2020, Beijing FMSoft Technologies Co., Ltd. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Or, As this program is a library, any link to this program must follow GNU General Public License version 3 (GPLv3). If you cannot accept GPLv3, you need to be licensed from FMSoft. If you have got a commercial license of this program, please use it under the terms and conditions of the commercial license. For more information about the commercial license, please refer to . \endverbatim */ /* * $Id: psos.h 7183 2007-05-16 08:19:34Z weiym $ * * MiniGUI for Linux/uClinux, eCos, uC/OS-II, VxWorks, * pSOS, ThreadX, NuCleus, OSE, and Win32. */ #ifndef _PSOS_H #define _PSOS_H #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ /* Timed out; returned only if a timeout was requested. */ #define ERR_TIMEOUT 0x01 /* Illegal system service function number. */ #define ERR_SSFN 0x03 /* Node specifier out of range. */ #define ERR_NODENO 0x04 /* object has been deleted. */ #define ERR_OBJDEL 0x05 /* object_id is incorrect; failed validity check */ #define ERR_OBJID 0x06 /* object type doesn't match object ID; failed validity check.*/ #define ERR_OBJTYPE 0x07 /* Node's object table full. */ #define ERR_OBJTFULL 0x08 /* Named object not found. */ #define ERR_OBJNF 0x09 /* Informative; files may be corrupted on restart. */ #define ERR_RSTFS 0x0D /* Exceeds node's maximum number of tasks. */ #define ERR_NOTCB 0x0E /* Insufficient space in Region 0 to create stack. */ #define ERR_NOSTK 0x0F /* Stack too small. */ #define ERR_TINYSTK 0x10 /* Priority out of range. For mu, the MU_PRIO_PROTECT flag has been specified. * The priority must be more than 0 and less than 256. */ #define ERR_PRIOR 0x11 /* Task already started. */ #define ERR_ACTIVE 0x12 /* Cannot restart; this task never was started. */ #define ERR_NACTIVE 0x13 /* Task already suspended. */ #define ERR_SUSP 0x14 /* The task was not suspended. */ #define ERR_NOTSUSP 0x15 /* Cannot change priority; new priority out of range. */ #define ERR_SETPRI 0x16 /* Register number out of range. */ #define ERR_REGNUM 0x17 /* pHILE+ resources in use. */ #define ERR_DELFS 0x18 /* pREPC+ resources in use. */ #define ERR_DELLC 0x19 /* pNA+ resources in use. */ #define ERR_DELNS 0x1A /* error cods for region manager are omitted ... */ /* error cods for partition manager are omitted ... */ /* Could not send a notification event. Error occurred while sending notification of message availability. */ #define ERR_NOTIFY 0x3D /* Exceeds node's maximum number of semaphores. */ #define ERR_NOSCB 0x41 /* No semaphore: this error code returns only if SM_NOWAIT was selected. */ #define ERR_NOSEM 0x42 /* Semaphore deleted while task waiting. */ #define ERR_SKILLD 0x43 /* Informative only; there were sm_delete tasks waiting. */ #define ERR_TATSDEL 0x44 /* Maximum number of tokens are already available for a semaphore that was created with the SM_BOUNDED flag. */ #define ERR_BOUND 0x45 /* ZERO bound count is invalid. */ #define ERR_INVBOUND 0x46 /* error cods for timer are omitted ... */ /* object not created from this node. */ #define ERR_ILLRSC 0x53 /* Cannot wait; the remote node is out of Agents. */ #define ERR_NOAGNT 0x54 /* object does not exist any more. */ #define ERR_STALEID 0x65 /* Remote node is no longer in service. */ #define ERR_NDKLD 0x66 /* Exceeds node's maximum number of mutexes. */ #define ERR_NOMUCB 0x70 /* The MU_GLOBAL flag cannot be specified with the MU_PRIO_INHERIT flag. */ #define ERR_NOGLOBAL 0x71 /* Informative only: there were tasks waiting. */ #define ERR_TATMUDEL 0x72 /* The mutex is not owned by the calling task. */ #define ERR_NOTOWNED 0x73 /* The mutex is already locked by the calling task and it was created with MU_NORECURSIVE flag. */ #define ERR_NORECURSIVE 0x74 /* Some other task has already locked the mutex; this error is returned only if MU_NOWAIT flag has been specified. */ #define ERR_MULOCKED 0x75 /* Mutex deleted while the task was waiting on it. */ #define ERR_MUKILLED 0x76 /* MU_FIFO flag cannot be specified with MU_PRIO_INHERIT or MU_PRIO_PROTECT. */ #define ERR_NOFIFO 0x77 /* Task was created with T_NORELMU flag set and currently owns some mutexes. */ #define ERR_OWNMUTX 0x79 /* Task¡¯s current priority exceedsthe ceiling priority of the guarding mutex. */ #define ERR_OUTCEIL 0x7A /* Expected mutex object; failed validity. The mutex is not of priority protected type. */ #define ERR_MUTYPE 0x8A /* other error cods are omitted ... */ /* system calls for ASR management */ #define T_PREEMPT 0x00000001 /* ASR is preemptible. */ #define T_NOPREEMPT 0x00000002 /* ASR is non-preemptible. */ #define T_TSLICE 0x00000010 /* ASR can be time-sliced. */ #define T_NOTSLICE 0x00000020 /* ASR cannot be time-sliced. */ #define T_ASR 0x00000100 /* ASR nesting enabled. */ #define T_NOASR 0x00000200 /* ASR nesting disabled. */ #define T_USER 0x00001000 /* ASR runs in user mode. */ #define T_SUPV 0x00002000 /* ASR runs in supervisor mode. */ #define T_ISR 0x00010000 /* Interrupts are enabled while ASR runs. */ #define T_NOISR 0x00020000 /* Interrupts are disabled while ASR runs. */ /* * This system call allows a task to specify an asynchronous signal routine * (ASR) to handle asynchronous signals. as_catch() supplies the starting * address of the task's ASR, and its initial execution mode. If the input * ASR address is zero, then the caller is deemed to have an invalid ASR, * and any signals sent to it will be rejected. * * A task's ASR gains control much like an ISR. If a task has pending signals * (sent via as_send()), then the next time the task is dispatched to run, * it will be forced to first execute the task's specified ASR. A task * executes its ASR according to the mode supplied by the as_catch() call * (for example, Non-preemptible, Time-slicing enabled, etc.) Upon entry to * the ASR, all pending signals - including all those received since the * last ASR invocation - are passed as an argument to the ASR. In addition, * a stack frame is built to facilitate the return from the ASR. * * as_catch() replaces any previous ASR for the calling task. Therefore, a * task can have only one ASR at any time. An ASR must exit using the * as_return() system call. */ unsigned long as_catch ( void (* start_addr) (unsigned long), /* ASR address */ unsigned long mode /* ASR attributes */ ); /* * This system call registers a set of bit-encoded events for the calling * task that are used to notify the posting of asynchronous signals to * the task. The event notification mechanism provides a way for a task to * synchronously wait for asynchronous signals via an ev_receive() call. */ unsigned long as_notify ( unsigned long events /* bit-encoded events */ ); /* * This system call must be used by a task's ASR to exit and return to * the original flow of execution of the task. The purpose of this call is * to enable the pSOS+ kernel to restore the task to its state before * the ASR. as_return() cannot be called except from an ASR. */ unsigned long as_return (void); /* * This system call sends asynchronous signals to a task. Additionally, * if signal notification via event has been requested, the notification * events are also posted to the task. The purpose of these signals is to * force a task to break from its normal flow of execution and execute * its Asynchronous Signal Routine (ASR). * * Asynchronous signals are like software interrupts, with ASRs taking on * the role of ISRs. Unlike an interrupt, which is serviced almost * immediately, an asynchronous signal does not immediately affect the * state of the task. An as_send() call is serviced only when the task is * next dispatched to run (and that depends on the state of the task and * its priority). * * Each task has 32 signals. These signals are encoded bit-wise in a single * long word. * * Like events, signals are neither queued nor counted. For example, if * three identical signals are sent to a task before its ASR has a chance * to execute, the three signals have the same effect as one. */ unsigned long as_send ( unsigned long tid, /* target task ID */ unsigned long signals /* bit-encoded signal list */ ); /* system calls for task management */ /* * This system call adds a task variable to a task. t_addvar() allocates to the specified * task a storage area which is used to hold a private copy of the specified variable. */ unsigned long t_addvar ( unsigned long tid, /* task identifier */ void **tv_addr, /* address of variable */ void *tv_value /* initial value for task variable */ ); #define T_GLOBAL 0x0001 #define T_LOCAL 0x0002 #define T_FPU 0x0010 #define T_NOFPU 0x0020 /* * This service call enables a task to create a new task. t_create() allocates to the * new task a Task Control Block (TCB) and a memory segment for its stack(s). The * task stack sizes and scheduling priority are established with this call. t_create() * leaves the new task in a dormant state; the t_start() call must be used to place * the task into the ready state for execution. */ unsigned long t_create ( char name[4], /* task name */ unsigned long prio, /* task priority */ unsigned long sstack, /* task supervisor stack size */ unsigned long ustack, /* task user stack size */ unsigned long flags, /* task attributes */ unsigned long *tid /* task identifier */ ); /* * This service call enables a task to delete itself or another task. The pSOS+ kernel * first dispatches any task deletion callouts, registered via the co_register() pSOS+ * service, in the reverse order of registration. When all of the deletion callouts have * finished, the pSOS+ kernel halts the task and reclaims its TCB, stack segment and * any allocated timers. * The calling task does not have to be the creator (parent) of the task to be deleted. * However, a task must be deleted from the node on which it was created. */ unsigned long t_delete ( unsigned long tid /* task identifier */ ); /* * This system call removes a task variable from a task. t_delvar() deallocates the * private storage allocated for the task variable. */ unsigned long t_delvar ( unsigned long tid, /* task identifier */ void **tv_addr /* address of variable*/ ); /* * This system call enables the caller to obtain the contents of a task's notepad register. * Each task has 16 such software registers, held in the task's TCB. The purpose * of these registers is to furnish every task with a set of named, permanent variables. * Eight of these registers are reserved for system use. Eight are free to be used for application * specific purposes. */ unsigned long t_getreg ( unsigned long tid, /* task identifier */ unsigned long regnum, /* register number */ unsigned long *reg_value /* register contents */ ); /* * This system call enables the calling task to obtain the task ID of a task it knows only * by name. This task ID can then be used in all other operations relating to the task. * Most system calls, except t_create() and t_ident(), reference a task by its task * ID. t_create() returns the task ID to a task's creator. For other tasks, one way to * obtain the task ID is to use t_ident(). */ unsigned long t_ident ( char name[4], /* task name */ unsigned long node, /* node number */ unsigned long *tid /* task ID */ ); #define TS_DEBUG 0x8000 /* Blocked by debugger */ #define TS_SUSP 0x4000 /* Suspended */ #define TS_TIMING 0x1000 /* Being timed */ #define TS_PAUSE 0x0800 /* Task paused */ #define TS_ABSTIME 0x0400 /* Timed for absolute time */ #define TS_VWAIT 0x0200 /* Waiting for events */ #define TS_SWAIT 0x0080 /* Waiting for semaphore */ #define TS_MWAIT 0x0040 /* Waiting for memory */ #define TS_QWAIT 0x0020 /* Waiting for message */ #define TS_RWAIT 0x0010 /* Waiting for reply packet */ #define TS_MUWAIT 0x0008 /* Waiting for mutex */ #define TS_CVWAIT 0x0004 /* Waiting for condition variable */ #define TS_CWAIT 0x0001 /* Waiting for component resource */ #define TS_READY 0x0000 /* Task is in Ready State */ struct tinfo { char name[4]; /* Task name */ unsigned long flags; /* Task attributes */ void (*iip)(void); /* Task's initial starting addr. */ unsigned long next; /* ID of the next waiting task */ unsigned short status; /* Task status.*/ unsigned char cpriority; /* Task's current priority.*/ unsigned char bpriority; /* Task's base priority */ unsigned char ipriority; /* Task's initial priority */ unsigned char evwantcond; /* Task's event wait condition */ unsigned short mode; /* Task's current mode.*/ unsigned short imode; /* Task's initial mode */ unsigned short amode; /* Task's ASR mode.*/ unsigned long tslice_quantum; /* Per task's time slice in ticks*/ long tslice_remain; /* Remainder time slice in ticks.*/ unsigned long wtobid; /* Object where task is blocked */ unsigned long evwait; /* Events - task waiting for.*/ unsigned long evcaught; /* Events caught */ unsigned long evrcvd; /* Events received */ unsigned long ss_size; /* Supervisor stack size */ unsigned long us_size; /* User stack size */ unsigned long *ssp; /* Current supervisor stack */ /* pointer */ unsigned long *issp; /* Initial supervisor stack pointer */ unsigned long *usp; /* Current user stack pointer */ unsigned long *iusp; /* Initial user stack pointer */ unsigned long imask; /* Interrupt priority level */ void (*asr_addr)(void); /* Task's ASR address */ unsigned long signal; /* Asynchronous signals pending */ unsigned long xdate; /* Timer expiry date */ unsigned long xtime; /* Timer expiry time */ unsigned long xticks; /* Timer expiry ticks */ unsigned long nrnunits; /* No. of region units wanted */ void **tsdp; /* Task_specific_Data pointer */ unsigned long co_toproc; /* Callouts to process */ unsigned long co_inprog; /* Callouts in progress */ unsigned long evasr_ntfy; /* ev used for ASR notification */ }; /* * This system call returns information of a specified task. The information includes * the static information that was specified at object creation time and certain internal * state information which is not static. */ unsigned long t_info ( unsigned long tid, /* Task ID */ struct tinfo *buf /* Object Information buffer */ ); #if 0 #define T_PREEMPT 0x0001 /* Task is preemptible. */ #define T_NOPREEMPT 0x0002 /* Task is non-preemptible. */ #define T_TSLICE 0x0004 /* Task can be time-sliced. */ #define T_NOTSLICE 0x0008 /* Task cannot be time-sliced. */ #define T_ASR 0x0010 /* Task's ASR is enabled. */ #define T_NOASR 0x0020 /* Task's ASR is disabled. */ #define T_USER 0X0040 /* Task runs in user mode. */ #define T_SUPV 0x0080 /* Task runs in supervisor mode. */ #define T_ISR 0x0100 /* Hardware interrupts are enabled while the task runs. */ #define T_NOISR 0x0200 /* Hardware interrupts are disabled while the task runs. */ #endif /* * This system call enables a task to modify certain execution mode fields. These are * preemption on/off, roundrobin on/off, asynchronous signal handling on/off, and * interrupt control. * Preemption has precedence over timeslicing. Therefore, if preemption is off, timeslicing * does not occur whether or not it is set. * The calling task can be preempted as a result of this call, if its preemptibility is * turned from off to on and a higher priority task is ready to run. * To obtain a task's current execution mode without changing it, use a mask of 0. */ unsigned long t_mode ( unsigned long mask, /* attributes to be changed */ unsigned long new_mode, /* new attributes */ unsigned long *old_mode /* prior mode */ ); /* * This system call forces a task to resume execution at its original start address regardless * of its current state or place of execution. If the task was blocked, the * pSOS+ kernel forcibly unblocks it. The task's priority and stacks are set to the original * values that t_create() specified. Its start address and execution mode are reset * to the original values established by t_start(). Any pending events, signals, or * armed timers are cleared. Thereafter, pSOS+ posts any "task restart callouts" that * are dispatched in the order they were registered when the task is scheduled to run. * All of the "task restart callouts" so dispatched run to completion before the task regains * control at its starting address. * The t_restart() call accepts a new set of up to four arguments, which, among * other things, can be used by the task to distinguish between the initial startup and * subsequent restarts. * The calling task does not have to be the creator (or parent) of the task it restarts. * However, a task must be restarted from the node on which it was created. */ unsigned long t_restart ( unsigned long tid, /* task identifier */ unsigned long targs[4] /* startup arguments */ ); /* * This system call removes the suspension of a task. If the task was suspended while * in the ready state, t_resume() releases it to be scheduled for execution. If the task * was both suspended and blocked (for example, waiting for a message), t_resume() * removes only the suspension. This leaves the task in the blocked state. */ unsigned long t_resume ( unsigned long tid /* task identifier */ ); /* * This system call enables the calling task to optionally obtain and modify either its * own or another task's base scheduling (software) priority. If oldprio is a non-NULL * address, the previous base scheduling priority is returned in the variable pointed to * by oldprio, regardless of the task's current priority. If the calling task issues * t_setpri() for a target task (self or another) with a valid non-0 value of newprio, * then the target task (whether it is running or not running) shall resume execution * after all other runnable tasks of equal or greater priority have been scheduled to * run. */ unsigned long t_setpri ( unsigned long tid, /* task identifier */ unsigned long newprio, /* new priority */ unsigned long *oldprio /* previous priority */ ); /* * This system call enables the caller to modify the contents of a task's notepad register. * Each task has 16 such software registers, held in the task's TCB. The purpose * of these registers is to furnish every task with a set of named, permanent variables. * Eight of these registers are reserved for system use, and eight are free to be used for * application-specific purposes. */ unsigned long t_setreg ( unsigned long tid, /* task identifier */ unsigned long regnum, /* register number */ unsigned long reg_value /* register value */ ); /* * This system call places a newly created task into the ready state to await scheduling * for execution. Thereafter, pSOS+ posts any "task startup callouts" that are dispatched * in the order they were registered when the task is scheduled to run. All of * the "task startup callouts" so dispatched run to completion before the task regains * control at its starting address. The calling task does not have to be the creator (or * parent) of the task to be started. However, a task must be started from the node on * which it was created. */ unsigned long t_start ( unsigned long tid, /* task identifier */ unsigned long mode, /* initial task attributes */ void (*start_addr) (unsigned long), /* task address */ unsigned long targs[4] /* startup task arguments */ ); /* * This system call suspends execution of a task until a t_resume() call is made for * the suspended task. The calling task suspends either itself or another task. The * t_suspend() call prevents the specified task from contending for CPU time but * does not directly prevent contention for any other resource. */ unsigned long t_suspend ( unsigned long tid /* task identifier */ ); /* * This system call enables the calling task to obtain and optionally modify its own or * another task's timeslice quantum. It allows applications to control how much execution * time is distributed among tasks with the same priority. It also returns the previous * timeslice quantum. */ unsigned long t_tslice ( unsigned long tid, /* task identifier */ unsigned long new_tslice, /* new timeslice value*/ unsigned long *old_tslice /* old timeslice value */ ); /* system calls for mutext */ #define MU_GLOBAL 0x0001 /* Mutex is globally addressable by other nodes of a multiprocessor system. The single-processor version of the pSOS+ kernel ignores MU_GLOBAL. */ #define MU_LOCAL 0x0002 /* Mutex can be addressed only by the local node where it was created. */ #define MU_RECURSIVE 0x0004 /* Mutex can be acquired in a recursive fashion. */ #define MU_NORECURSIVE 0x0008 /* Mutex cannot be acquired in a recursive fashion. */ #define MU_FIFO 0x0010 /* The waiting tasks are queued in the FIFO order. This flag can be specified with MU_PRIO_NONE flag, but not with MU_PRIO_INHERIT or MU_PRIO_PROTECT. */ #define MU_PRIOR 0x0020 /* The waiting tasks are queued in decreasing order of their current priority. */ #define MU_PRIO_NONE 0x0100 /* Mutex does not protect against unbounded priority inversion. */ #define MU_PRIO_INHERIT 0x0200 /* Mutex uses the priority inheritance protocol to prevent unbounded priority inversion. */ #define MU_PRIO_PROTECT 0x0400 /* Mutex uses the priority protect protocol to prevent unbounded priority inversion. */ /* * This system call creates a mutex and initializes it according to the specifications * supplied with the call. */ unsigned long mu_create ( char name[4], /* user assigned name */ unsigned long flags, /* mutex attributes */ unsigned long ceiling, /* ceiling priority */ unsigned long *muid /* newly created mutex id */ ); /* * This system call deletes a mutex with the specified mutex ID and frees the associated * kernel resources. This call can be made only from the node where the specified * mutex was created. * The mu_delete() system call can be invoked by any task, and not necessarily the * task that originally created the mutex. In the event that there are other tasks waiting * to acquire that mutex, the tasks are unblocked and an error code is returned to * them. */ unsigned long mu_delete ( unsigned long muid /* MUTEX identifier */ ); /* * This system call enables the calling task to obtain the mutex ID of a mutex it only * knows by name. This mutex ID can be used in all other operations relating to the * mutex. * The pSOS+ kernel does not check for duplicate names. If multiple mutexes with the * same name exist, either on the local node, or on a remote note in a multi-processor * system, a mu_ident() call may return the ID of any one mutex with the specified * name. It can't be ascertained which ID is returned, though, to a certain extent it depends * on the standard search order followed by pSOS+ kernel, as defined in the * pSOSystem System Concepts manual. */ unsigned long mu_ident ( char name[4], /* mutex name */ unsigned long node, /* node number */ unsigned long *muid /* mutex identifier */ ); struct muinfo { char name[4]; /* Name of the Mutex */ unsigned long flags; /* Mutex attributes */ unsigned long wqlen; /* No. of waiting tasks */ unsigned long wtid;/* ID of the first waiting task */ unsigned long count; /* Mutex reference count */ unsigned long ownid; /* ID of mutex owner */ unsigned long node; /* Owner task's node number */ unsigned long ceilprio; /* ceiling priority for MU_PROTECT mutexes */ unsigned long phpwt; /* Highest of all waiting task priorities */ }; /* * This system call provides information of a specified Mutex object. The information * includes the static information that was specified at object creation time and certain * internal state information which is not static. */ unsigned long mu_info ( unsigned long muid, /* Mutex ID */ struct muinfo *buf /* Object Information buffer */ ); #define MU_WAIT 0x01 /* If the mutex is locked, block until it is available. */ #define MU_NOWAIT 0x02 /* Return with error if the mutex is locked. */ /* * This system call allows a task to lock a mutex specified by the muid argument. If the * mutex is not locked by another task, the mutex is put in the locked state, and the * calling task becomes the owner of the mutex. If the mutex was created with the * MU_RECURSIVE attribute set (see mu_create on page 2-87), a task can invoke * mu_lock() multiple times to acquire the same mutex in a recursive fashion. The * same number of mu_unlock() calls must then be made by the same task to release * the mutex. A mutex created with the MU_NORECURSIVE flag can be locked only once * by any task. If the task calls mu_lock again while it is holding the mutex, the call * will return with an error. * If the mutex is locked by another task then, depending on the flags argument, the * calling task is either put in the blocked state and is queued in the wait queue associated * with the mutex, or an error is returned. */ unsigned long mu_lock ( unsigned long muid, /* mutex identifier */ unsigned long flags, /* call attributes */ unsigned long timeout /* timeout interval */ ); /* * This system call enables the calling task to optionally obtain and modify a mutex's * ceiling priority. The call only operates on mutexes that have been created with the * MU_PRIO_PROTECT flag. If oldprio is a non-NULL address, the previous ceiling priority * is returned in the variable pointed to by oldprio. * The mu_setceil() call either locks the mutex if it is unlocked, or blocks until it * can successfully lock the mutex; then it changes the priority ceiling of the mutex * and releases the mutex. If the calling task already owns the mutex when it invokes * the mu_setceil() call with a valid non-0 value of newprio, then the task's current * priority may change according to the priority protect protocol. */ unsigned long mu_setceil ( unsigned long muid, /* mutex identifier */ unsigned long newprio, /* new ceiling priority */ unsigned long *oldprio /* previous ceiling priority */ ); /* * This system call allows a task to unlock a mutex specified by the muid argument. If * the caller currently owns the mutex then mu_unlock() call decreases the recursive * level associated with the mutex. If the recursive level reaches zero, the mutex is unlocked * and the calling task loses ownership of the mutex. An error is returned if the * calling task does not currently own the mutex. * For mutexes which have not been created with the MU_PRIO_PROTECT flag, when * the calling task loses the ownership of the mutex, and if any tasks are waiting to * lock the mutex, the ownership of the mutex is transferred to the waiting task at the * head of the mutex's wait queue. It is unblocked, and made ready-to-run. * For mutexes which have been created with the MU_PRIO_PROTECT flag, when the * calling task loses ownership of the mutex, there could be tasks waiting at the mutex's * wait queue, on one of two action types. If the task at the head of the queue is * waiting to lock the mutex, the ownership of the mutex is transferred to the waiting * task, and its priority is raised if necessary. It is unblocked, and made ready-to-run. * If the task at the head of the queue is waiting to change the ceiling priority of the * mutex, the ceiling priority is modified, the task is unblocked and made ready-torun; * and the next task in the waiting queue is checked. This process of determining * the requested action type associated with a waiting task goes on till either the queue * is empty, or a task which can successfully lock the mutex is found. */ unsigned long mu_unlock ( unsigned long muid /* mutex identifier */ ); /* * This system call is used to asynchronously release a semaphore token. It is identical * to sm_v() except the call is made asynchronously. Refer to the description of * sm_v() for further information. This call is only supported by the pSOS+m kernel * (the multiprocessor version). */ unsigned long sm_av ( unsigned long smid /* semaphore identifier */ ); #define SM_GLOBAL 0x0001 /* Semaphore can be addressed by other nodes. */ #define SM_LOCAL 0x0002 /* Semaphore can be addressed by local node only. */ #define SM_PRIOR 0x0004 /* Tasks are queued by priority. */ #define SM_FIFO 0x0008 /* Tasks are queued by FIFO. */ #define SM_UNBOUNDED 0x0010 /* Semaphore count is not bounded. */ #define SM_BOUNDED 0x0020 /* Semaphore count is bounded. When the SM_BOUNDED flag is specified the count parameter specifies the initial semaphore token count, as well as the upper bound of available tokens. */ /* * This system call creates a semaphore by allocating and initializing a Semaphore * Control Block (SMCB) according to the specifications supplied with the call. * Like all objects, a semaphore has a user-assigned name, and a pSOS+-assigned * semaphore ID returned by sm_create(). Several flag bits specify the characteristics * of the semaphore, including whether tasks will wait for the semaphore by task * priority or strictly FIFO. */ unsigned long sm_create ( char name[4], /* semaphore name */ unsigned long count, /* number of tokens */ unsigned long flags, /* semaphore attributes */ unsigned long *smid /* semaphore identifier */ ); /* * This system call deletes the semaphore with the specified semaphore ID, and frees * the SMCB to be reused. sm_delete() takes care of cleaning up the semaphore. If * there are tasks waiting, they will be unblocked and given an error code. * The calling task does not have to be the creator (parent) of the semaphore to be deleted. * However, a semaphore must be deleted from the node on which it was created. */ unsigned long sm_delete ( unsigned long smid /* semaphore ID */ ); /* * This system call enables the calling task to obtain the semaphore ID of a semaphore * it only knows by name. The semaphore ID can then be used in all other operations * relating to this semaphore. * Most system calls, except sm_create() and sm_ident(), reference a semaphore * by the semaphore ID. sm_create() returns the semaphore ID to the semaphore * creator. For other tasks, one way to obtain the semaphore ID is to use sm_ident(). */ unsigned long sm_ident ( char name[4], /* semaphore name */ unsigned long node, /* node selector */ unsigned long *smid /* semaphore ID */ ); struct sminfo { char name[4]; /* Name of semaphore */ unsigned long flags; /* Semaphore attributes */ unsigned long wqlen; /* No. of waiting tasks */ unsigned long wtid; /* ID of the first waiting task */ unsigned long count; /* Semaphore count */ unsigned long maxcount; /* Limit for bounded semaphores */ unsigned long tid_ntfy; /* Task to notify of availability */ unsigned long ev_ntfy; /* Ev to post to notify availability */ }; /* * This system call returns information of a specified Semaphore object. The information * includes the static information that was specified at object creation time and * certain internal state information which is not static. */ unsigned long sm_info ( unsigned long smid, /* Semaphore ID */ struct sminfo *buf /* Object Information buffer */ ); /* * This system call registers a set of bit-encoded events and a task ID for the given * semaphore. Once so registered, a notification is sent to the task whenever a semaphore * token becomes available, via an implicit call of the form: ev_send(tid, * events). The task can choose to receive the notification via ev_receive() call. */ unsigned long sm_notify ( unsigned long smid, /* ID of target semaphore */ unsigned long tid, /* ID of task to be notified */ unsigned long events /* bit-encoded events */ ); #define SM_WAIT 0x01 /* Block until semaphore is available. */ #define SM_NOWAIT 0x02 /* Return with error code if semaphore is unavailable. */ /* * This system call enables a task or an ISR to acquire a semaphore token. A calling * task can specify whether or not it wants to wait for the token. If the semaphore token * count is positive, then this call returns the semaphore token immediately. If the * semaphore token count is zero and the calling task specified SM_NOWAIT, then * sm_p() returns with an error code. If SM_WAIT is elected, the task will be blocked * until a semaphore token is released, or if the timeout argument is specified, until * timeout occurs, whichever occurs first. */ unsigned long sm_p ( unsigned long smid, /* semaphore identifier */ unsigned long flags, /* attributes */ unsigned long timeout /* timeout */ ); /* * This system call is used to release a semaphore token. If a task is already waiting at * the semaphore, it is unblocked and made ready to run. If there is no task waiting, * then the semaphore token count is simply incremented by 1. * If, as a result of this call, a semaphore token becomes available, and a set of task * and events had been registered via a prior call to sm_vnotify() to notify the availability * of the semaphore token, pSOS+ also performs an ev_send() operation to * send the registered events to the registered task. */ unsigned long sm_v ( unsigned long smid /* semaphore identifier */ ); /* * This system call asynchronously removes all tasks from a condition-variable¡¯s wait * queue. It is identical to cv_broadcast() except that the call is made asynchro- * nously. Refer to the description of cv_broadcast() for further information. */ unsigned long cv_abroadcast ( unsigned long cvid /* condition variable identifier */ ); /* * This system call asynchronously removes the task at the head of a condition- * variable¡¯s queue. It is identical to cv_signal() except that the call is made asyn- * chronously. Refer to the description of cv_signal() for further information. */ unsigned long cv_asignal ( unsigned long cvid /* condition variable ID */ ); /* * This system call removes all the tasks from a condition variable¡¯s wait queue. If the * mutex guarding the condition variable is unlocked, the task at the head of the wait * queue is given ownership of the guarding mutex and unblocked. The remaining * tasks, including the task at the head of the wait queue if the guarding mutex is * locked, are placed in the guarding mutex¡¯s wait queue. * If there are no tasks waiting, then cv_broadcast() does not do anything. */ unsigned long cv_broadcast ( unsigned long cvid /* condition variable identifier */ ); /* * This system call creates a condition variable and initializes it according to the * specifications supplied with the call. * Like all objects, a condition variable has a user-assigned name and a pSOS- * assigned condition variable ID returned by cv_create(). Several flag bits specify * the characteristics of the condition variable. Tasks can wait at the condition variable * either by task priority or strictly FIFO. */ unsigned long cv_create ( char name[4], unsigned long flags, unsigned long *cvid ); /* * This system call deletes a condition variable specified by its ID (cvid) and frees the * associated kernel resources. If there are tasks waiting at the condition variable, the * tasks are unblocked and given an error code. * The calling task does not have to be the creator of the condition variable to be de- * leted. However, a condition variable must be deleted from the node on which it was * created. */ unsigned long cv_delete ( unsigned long cvid /* condition variable identifier */ ); /* * This system call enables the calling task to obtain the ID of a condition variable it * only knows by name. This condition variable ID can be used in all other operations * relating to the condition variable. * The pSOS+ kernel does not check for duplicate names. If multiple condition vari- * ables with the same name exist, either on the local node, or on a remote note in a * multi-processor system, a cv_ident() call may return the ID of any one condition * variable with the specified name. It can¡¯t be ascertained which ID is returned, * though; to a certain extent it depends on the standard search order followed by * pSOS+ kernel, as defined in the pSOSystem System Concepts manual. */ unsigned long cv_ident ( char name[4], /* condition variable name */ unsigned long node, /* node number */ unsigned long *cvid /* condition variable identifier */ ); #if 0 /* * This system call returns object information for a given condition variable object. The * information includes the static information that was specified at object creation * time and certain internal state information which is not static. */ unsigned long cv_info ( unsigned long cvid, struct cvinfo *buf ); #endif /* * This system call removes the task at the head of a condition variable¡¯s wait queue * from that queue. If the mutex guarding the condition variable is unlocked, the task * is given ownership of the guarding mutex and unblocked. If the mutex is already * locked, then the task is placed in the guarding mutex¡¯s wait queue according to the * queueing policy of the mutex. * If there are no tasks waiting at the condition variable, this call does nothing. */ unsigned long cv_signal ( unsigned long cvid /* condition variable identifier */ ); /* * This system call is used by a task to wait on a condition variable. The guarding mu- * tex must be owned by the caller. If tasks are waiting at the condition variable, then * muid must specify the mutex already guarding the condition variable. Otherwise, * any mutex may be specified. * cv_wait() unlocks the guarding mutex and blocks the calling task. Unless a time- * out occurs, the calling task waits at the condition variable until removed from the * wait queue by a cv_signal() or a cv_broadcast() call. When removed, owner- * ship of the guarding mutex is given to the task if the guarding mutex is currently * unlocked. Otherwise, the task waits for ownership of the guarding mutex according * to the queueing policy of the mutex. */ unsigned long cv_wait ( unsigned long cvid, /* condition variable identifier */ unsigned long muid, /* mutex identifier */ unsigned long timeout /* timeout interval */ ); /* * This system call returns the address of the calling task's internal errno variable. * The pSOS+ kernel maintains an internal errno variable for every task. Whenever * an error is detected by any pSOSystem component, the associated error code is * stored into the running task's internal errno variable. The error code can then be * retrieved by referencing the errno macro de????ed in the header ????e as * follows: * #define errno (*(errno_addr()) * For example, the following statement expands to include a call to errno_addr(): * if (errno == ERR_NOMGB) */ unsigned long *errno_addr (void); #ifdef __cplusplus } #endif /* __cplusplus */ #endif /* _PSOS_H */