GLAST/LAT > DAQ and FSW > FSW > Doxygen Index > IPBS / V0-0-1
Constituent: pbs     Tag: i845e
#include <stdio.h>
#include <string.h>
#include "PBI/Ofs.h"
#include "IPBS/PL.ih"
#include "IPBS/LI.ih"
#include "IPBS/TASK.h"
#include "IPBS/TOC.h"
#include "TASK_pvtdefs.h"
#include "IPBS/FORK.h"
Include dependency graph for FORK.c:
Data Structures | |
union | _FORK_que |
Structure defining a FORK_que. More... | |
union | _FORK_que_head |
Structure defining a FORK_que_head. The FORK routines are set up to manage to types of ques, a simply linked list or a Priority List of ques. This is simply a union of the controlling list heads. More... | |
struct | _FORK_fcb |
Defines Fork Control Block containing the global information about the FORK que. More... | |
Typedefs | |
typedef _FORK_que_head | FORK_que_head |
Typedef for a FORK_que_head. | |
typedef enum _FORK_msg_type | FORK_msg_type |
Typedef for enum FORK_msg_type. | |
Enumerations | |
enum | _FORK_msg_type { FORK_K_MSG_TYPE_USR = 0, FORK_K_MSG_TYPE_SYS = 1 } |
Distinguishes between the two types of messages, user or system. More... | |
Functions | |
int | FORK_fcb_sizeof (int nques) |
Returns the size, in bytes, of a FORK Control Block. | |
int | FORK_create (FORK_fcb *fcb, const struct _TASK_attr *attributes, FORK_cb_rtn def_handler, FORK_cb_prm ctx, FORK_cb_prm tmo_ctx, const TOC *tmo_toc, int nques, const FORK_que_cfg *que_cfg, FORK_type msg_type, FORK_msg_sys *msg_blks, int msg_cnt) |
Creates a FORK message que. | |
FORK_que * | FORK_que_get (FORK_fcb *fcb, int que_id) |
Returns a handle to the specified que. | |
int | FORK_destroy (FORK_fcb *fcb) |
Destroys a FORK que. | |
FORK_que_list | FORK_disable (FORK_fcb *fcb, FORK_que_list disable_list) |
Disables the servicing of the specified ques. | |
FORK_que_list | FORK_enable (FORK_fcb *fcb, FORK_que_list enable_list) |
Enables the servicing of the specified ques. | |
FORK_que_list | FORK_enabled (const FORK_fcb *fcb) |
Returns the enable/disabled state of the specified que. | |
int | FORK_qdisable (FORK_que *que) |
Disables the servicing of the specified que. | |
int | FORK_qenable (FORK_que *que) |
Enables the servicing of the specified que. | |
int | FORK_qenabled (const FORK_que *que) |
Returns the enable/disabled state of all ques. | |
int | FORK_qhead_modify (FORK_que *que, FORK_cb_modify modify, void *context) |
Sneaky way to modify the head (oldest) element on the specified FORK que. | |
int | FORK_qtail_modify (FORK_que *que, FORK_cb_modify modify, void *context) |
Sneaky way to modify the tail (newest) element on the specified FORK que. | |
int | FORK_qsys (FORK_que *que, FORK_cb_rtn handler, void *contents) |
Ques a message using the internal FORK message blocks. | |
int | FORK_qsysW (FORK_que *que, FORK_cb_rtn handler, void *contents) |
Ques a message using the internal FORK message blocks. | |
int | FORK_qsysW_toc (FORK_que *que, FORK_cb_rtn handler, void *contents, const TOC *tmo_toc) |
Ques a message using the internal FORK message blocks. | |
int | FORK_qusr (FORK_que *que, FORK_cb_rtn handler, FORK_msg_hdr *msg_hdr) |
Ques a user composed message. | |
int | FORK_resume (FORK_fcb *fcb) |
Resumes a previously suspended FORK task. | |
int | FORK_suspend (FORK_fcb *fcb) |
Suspends the FORK task. | |
int | FORK_join (FORK_fcb *fcb, int *exit_status) |
Waits until the FORK'd task is deleted. |
CVS $Id: FORK.c,v 1.1.1.1 2006/02/10 21:45:33 saxton Exp $
1. The FORK routines allow user controller over memory allocation.
The msgQ routines allocate memory when a request to send a message is made. If no memory is available, the user may either have the call return with failure or block. Ignoring the 'return with failure option' a problem occurs when blocking is not an option, as in an interrupt service routine. The FORK routines allow the user to pre-allocate the message buffer before committing to servicing an interrupt. This ensures that the necessary resources are in hand.
2. The burden of creating the receiving task is taken on by the FORK_create() routine.
Since the metaphor of the FORK routines is to transparently fork the execution path, this seems more natural than manually creating an task/thread to handle the messages. In most cases, this is all the create task is going to do, ie pend on a message que and service the incominig messages.
3. The messsage to be queued is not copied twice as it is in the VxWorks routines (once when sending and once when receiving).
This is a direct consequence of allowing the user to do his own management of the message buffers. Many times memory allocation can be avoid altogether. All the FORK routines demand is two free 32 bit locations (one for a link management and the other for a dispatch routine). Both locations are used only when on the FORK que. Many times the user can find two free location in the piece of information being sent, thus avoiding allocation (and, more importantly, handling the case of failure to allocate) altogether.
4. The FORK routines offer the option of managing a number (up to 32) priority order ques.
This feature allows higher priority messages to be serviced first, effectively creating an out-of-band mechanism.
A good use for these would be a command receiver/command handler. Assuming the receiver and handler are in different threads, the receiver receives incoming commands, decides which FORK que they should be assigned to and the function that such be executed. The received packages this information along with the command parameters and ques it. The handler thread wakes out and executes the command.
This latter design choice has only a slight impact on performance, since, in theory, the dispatch routine could release the message memory earlier. However, given the single reader nature of the FORK utilities, only one such buffer can be outstanding at an given time. The truly concerned user can avoid this limitation by using only message buffers that he manages.
int test_fork (void) { FORK_fcb *fcb; FORK_que *que; int size; int exit_status; / * Allocate 10 message blocks for the FORK ques internal pool * / FORK_msg_sys msg_blks[10]; int msg_blk_cnt = sizeof (msg_blks) / sizeof (*msg_blks); size = FORK_fcb_sizeof (1); / * Size of Fork Control Block * / fcb = (FORK_fcb *) MBA_alloc (size); / * Allocate the memory for it * / / * Create the fork que * / status = FORK_create (fcb, / * Fork Control Block to init * / NULL, / * Use default task attributes * / normalPrint, / * Default handling routine * / forkParameter, / * Parameter passed to handler * / forkTmoParameter, / * Parameter passed if timeout * / TOC_FOREVER, / * How long to pend before tmo * / 1, / * One internal FORK que * / NULL, / * Individual que cfg's * / FORK_K_TYPE_PENDING_WTO,, / * FIFO style blocking when * / / * allocating system messges * / msg_blks, / * A source of message blocks * / msg_blk_cnt) / * Number of messge blocks * / / * | Retrieve the que to post messages to. In this example the FORK | routines were initialized to support only a single que, so the | que to be located in que = 0 / que = FORK_get_que (fcb, 0); / * Post a series of messages to this que * / status = FORK_qsysW (que, NULL, "Hello World\n"); status = FORK_qsysW (que, boldPrint, "Goodbye World\n"); status = FORK_qsysW (que, winddown, "Killing FORK'd task\n"); status = FORK_join (que, &exit_status); / * | All done, kill the que. Note that this call blocks until the | the FORK'd task has completed its work. / status = FORK_destroy (fcb); free (fcb); return 0; } int normalPrint (void *parameter, FORK_msg_sys *msg) { fputs (msg->contents); return FORK_C_CONTINUE; } int boldPrint (void *parameter, FORK_msg_sys *msg) { printf ("%s", BOLD_ESC_SEQUENCE); fputs (msg->contents); printf ("%s", NORMAL_ESC_SEQUENCE); return FORK_C_CONTINUE; } int winddown (void *parameter, FORK_msg_sys *msg) { fputs (msg->contents); fflush (stdout); / * Indicate that this is it * / return 1; }
|
Distinguishes between the two types of messages, user or system.
|
|
Creates a FORK message que.
|
|
Destroys a FORK que.
The usual method of winding down the FORK task is for the parent task to send a QUIT message to the FORK'd task. The parent task then calls FORK_join, which block until the FORK'd task exits. The FORK'd task performs any necessary clean-up then returns a non-zero status code from the callback routine. This causes the FORK'd task to delete itself, allowing the FORK_join() call to complete.
|
|
Disables the servicing of the specified ques.
|
|
Enables the servicing of the specified ques.
|
|
Returns the enable/disabled state of the specified que.
|
|
Returns the size, in bytes, of a FORK Control Block.
The FORK routines are capable of supporting multiple prioritized internal ques. This is done by specifying nques to be greater than 1. |
|
Waits until the FORK'd task is deleted.
The usual method of winding down the FORK task is for the parent task to send a QUIT message to the FORK'd task. The parent task then calls FORK_join, which block until the FORK'd task exits. The FORK'd task performs any necessary clean-up then returns a non-zero status code from the callback routine. (This status code is returned to the user as exit_status.) This causes the FORK'd task to delete itself, allowing the FORK_join() call to complete. The user is then free to call FORK_destroy() to return the resources garnered by the FORK fcb. Note that the exit_status may be returned as any non-zero 32-bit value. This includes returning a pointer to a structure which may contain additional information. If one does this, one must be careful to ensure that the memory is viable after task deletion. For instance, don't return pointers to things on the stack. |
|
Disables the servicing of the specified que.
|
|
Enables the servicing of the specified que.
|
|
Returns the enable/disabled state of all ques.
|
|
Sneaky way to modify the head (oldest) element on the specified FORK que.
|
|
Ques a message using the internal FORK message blocks.
Note that because the message is internally allocated it may be possible that this list is exhausted. This version of the routine returns immediately with failure if the list is exhausted. See FORK_qsysW() or FORK_qsysW_toc for wait forever and wait with a timeout versions |
|
Ques a message using the internal FORK message blocks.
Note that because the message is internally allocated it may be possible that this list is exhausted. This version of the routine waits indefinitely until a message becomes available. See FORK_qsys() or FORK_qsysW_toc for no wait and wait with timeout versions. |
|
Ques a message using the internal FORK message blocks.
Note that because the message is internally allocated it may be possible that this list is exhausted. A timeout parameter is provided to handle this situation. See FORK_qsys() or FORK_qsysW for no wait and wait forever versions. |
|
Sneaky way to modify the tail (newest) element on the specified FORK que.
|
|
Returns a handle to the specified que.
|
|
Ques a user composed message.
For the extra work involved in using this routine, the user gets to control his own memory allocation and the exact contents of the message. This means that there is almost no case, other than an internal corruption, under which this routine can fail. |
|
Resumes a previously suspended FORK task.
|
|
Suspends the FORK task.
|