tk_def_ssy

De.ne Subsystem

[C Language Interface]

ER ercd = tk_def_ssy ( ID ssid, T_DSSY *pk_dssy ) ;

[Parameters]

ID ssid Subsystem ID

T_DSSY* pk dssy ubsystem definition information

pk dssy detail:

ATR ssyatr Subsystem attributes

PRI ssypri Subsystem priority

FP svchdr Extended SVC handler address

FP breakfn Break function address

FP startupfn Startup function address

FP cleanupfn Cleanup function address

FP eventfn Event handling function address

INT resblksz Resource control block size (in bytes)

(Other implementation-dependent parameters may be added beyond this point.)

[Return Parameters]

ER ercd Error code

[Error Codes]

E_OK Normal completion

E_ID Invalid ID number (ssid is invalid or cannot be used)

E_NOMEM Insufficient memory (memory for control block cannot be allocated)

E_RSATR Reserved attribute (svcatr is invalid or cannot be used)

E_PAR Parameter error (pk dssy is invalid or cannot be used)

E_OBJ ssid is already defined (when pk dssy = NULL)

E_NOEXS ssid is not defined(when pk dssy = NULL)

[Description]

De.nes subsystem ssid.

One subsystem ID must be assigned to one subsystem without overlapping with other subsystems. The OS does not have a function for assigning these automatically.

Subsystem IDs 1 to 9 are reserved for T-Kernel use. 10 to 255 are numbers used by middleware, etc. The maximum usable subsystem ID value is implementation-dependent and may be lower than 255 in some implementations.

ssyatr indicates system attributes in its low bits and implementation-dependent attributes in the high bits. The system attributes in ssyatr are not assigned in this version, and no system attributes are used.

ssypri indicates the subsystem priority. The startup function, cleanup function, and event handling function are called in order of priority. The order of calling when priority is the same is undefined. Subsystem priority 1 is the highest priority, with larger numbers indicating lower priorities. The range of priorities that can be specified is implementation-dependent, but it must be possible to assign at least priorities 1 to 16.

NULL can be specified in breakfn, startupfn, cleanupfn, and eventfn, in which case the corresponding function will not be called.

Specifying pk dssy = NULL deletes a subsystem definition. The ssid subsystem resource control block will also be deleted.

  • Resource control block

The resource control block de.nes groups of resources and manages them by their attributes and other factors. Each resource group is allocated its own memory space of the size specified in resblksz. If resblksz = 0 is specified, no resource control block is allocated; but a Resource ID (see tk_cre_res) is assigned even in this case.

Each task belongs to one resource group or another. When a task makes a request to a subsystem and resources are allocated to that task in the subsystem, the allocation information is stored in the resource control block. The subsystem decides what kinds of resources to register in the resource control block and how they are to be registered.

The OS is not involved in the contents of the resource control block; it can be used freely by the subsystem. The size specified in resblksz should, however, be as small as possible. If a larger memory block is needed, the subsystem must allocate that memory on its own and register its address in the resource control block.

A resource control block is resident memory located in shared (system) space.

  • Extended SVC handler

An extended SVC handler accepts requests from applications and other programs as an application programming interface (API) for a subsystem. It can be called in the same way as an ordinary system call, and is normally invoked using a trap instruction or the like.

The format of an extended SVC handler is as follows.


	INT svchdr( VP pk_para, FN fncd )
	{
		/*
		Branching by fncd
		*/
		return retcode; /* exit extended SVC handler */
	}

fncd is a function code. The low 8 bits of the instruction code are the subsystem ID. The remaining high bits can be used in any way by the subsystem. Ordinarily they are used as a function code inside the subsystem. A function code must be a positive value, so the most signi.cant bit is always 0.

pk_para points to a packet of parameters passed to this system call. The packet format can be decided by the subsystem. Generally a format like the stack passed to a C language function is used, which in many cases is the same format as a C language structure.

The return code passed by an extended SVC handler is passed to the caller transparently as the function return code. As a rule, negative values are error codes and 0 or positive values are the return code for normal completion. If an extended SVC call fails for some reason, OS error code (negative value) is returned to the caller without invoking the extended SVC handler, so it is best to avoid confusion with these values.

The format by which an extended SVC is called is dependent on the OS implementation. As a subsystem API, however, it must be specified in a C language function format independent of the OS implementation. The subsystem must provide an interface library for converting from the C language function format to the OS-dependent extended SVC calling format.

An extended SVC handler runs as a quasi-task portion. It can be called from a task-independent portion, and in this case the extended SVC handler also runs as a task-independent portion.

  • Break function

A break function is a function called when a task exception is raised for a task while an extended SVC handler is executing.

When a break function is called, the processing by the extended SVC handler running at the time the task exception was raised must be stopped promptly and control must be returned from the extended SVC handler to its caller. The processing for stopping the processing by the currently running extended SVC handler is called a break function.

The format of a break function is as follows.


	void breakfn( ID tskid )
	{
		/*
		Stop the running extended SVC handler
		*/
	}

tskid is the ID of the task where the task exception was raised.

A break function is called when a task exception is raised by tk_ras_tex. If extended SVC handler calls are nested, then when return is made from an extended SVC handler and the nesting level drops by 1, the extended SVC handler corresponding to the return destination is the one called.

A break function is called one time only for one extended SVC handler per one task exception.

If another nested extended SVC call is made while a task exception is raised, no break function is called for the called extended SVC handler.

A break function runs as a quasi-task portion. Its task context is either that of the task that called tk_ras_tex or that of the task where the task exception was raised (the task running an extended SVC handler). In the former case, the break function runs when tk_ras_tex is called, while in the latter case the break function runs when extended SVC nesting is reduced by one level. This means it is possible that the task executing the break function will be di.erent from the task executing the extended SVC handler. In such a case the break function and extended SVC handler run concurrently as controlled by task scheduling. It is thus conceivable that the extended SVC handler will return to its caller before the break function .nished executing, but in that case the extended SVC handler waits at the point right before returning, until the break function completes. How this wait state maps to the task state transitions is implementation-dependent, but preferably it should remain in READY state (a READY state that does not go to RUN state). The precedence of a task may change while it is waiting for a break function to complete, but how task precedence is treated is implementation-dependent. Similarly, an extended SVC handler cannot call an extended SVC until break function execution completes. In other words, during the time from the raising of a task interrupt until the break function completes, the affected task must stay in the extended SVC handler that was executing at the time of the task exception.

If a break function and extended SVC handler run in di.erent task contexts and the break function task priority is lower than the extended SVC handler task priority, the task priority of the break function is raised to the same priority as the extended SVC handler task only during the time while the break handler is executing. On the other hand, if the break function task priority is the same as or higher than that of the extended SVC handler, the priority does not change. The priority that gets changed is the current priority; the base priority stays the same. The change in priority occurs only right before entry into the break function; any changes after that in the extended SVC handler task priority are not followed up by further changes in priority of the break function task. In no case does a change in the break function priority while a break function is running result in a priority change in the extended SVC handler task. At the same time there is no restriction on priority changes because a break function is running. When the break function completes, the current priority of its task reverts to base priority. If a mutex was locked, however, the priority reverts to that as adjusted by the mutex. (In other words, the ability is provided to adjust the current priority at the entry and exit of the break function only; other than that, the priority is the same as when an ordinary task is running.)

  • Startup function

A startup function is called by issuing the tk_sta_ssy system call. It performs resource control block initialization processing.

The format of a startup function is as follows.


	void startupfn( ID resid, INT info )
	{
		/*
		Resource control block initialization processing
		*/
	}

resid is the ID of the resource group to be initialized, and info is a parameter that can be used in any way. Both are passed to tk_sta_ssy.

Even if initialization of the resource control block fails for some reason, the startup function must be terminated normally. If the resource control block could not be initialized, then when an API (extended SVC) that cannot be executed normally as a result is called, error is passed in the return code of that API.

A startup function runs as a quasi-task portion in the context of the task that called tk_sta_ssy.

  • Cleanup function

A cleanup function is called by issuing the tk_cln_ssy system call, and performs resource release

processing.

The format of a cleanup function is as follows.


	void cleanupfn( ID resid, INT info )
	{
		/*
		Resource release processing
		*/
	}

resid is the ID of the resource group subject to resource release, while info is a parameter that can be used freely. Both areparameters passed to tk_cln_ssy.

Even if resource release fails for some reason, the cleanup function must be terminated normally. The error handling, such as logging of errors, can be decided for each subsystem.

After the cleanup function completes its processing, the resource control block is automatically cleared to 0. If no cleanup function was defined (cleanupfn = NULL), the tk_cln_ssy system call clears the resource control block to 0.

A cleanup function runs as a quasi-task portion in the context of the task that called tk_cln_ssy.

  • Event handling function

An event handling function is called by issuing the tk_evt_ssy system call. It processes various requests made to a subsystem. Note that it does not carry the obligation to process all requests for all subsystems. If processing is not required, it can simply return E_OK without performing any operation.

The format of an event handling function is as follows.


	ER eventfn( INT evttyp, ID resid, INT info )
	{
		/*
		Event processing
		*/
		return ercd;
	}

evttyp indicates the request type, resid gives the ID of the resource group, and info is a parameter that can be used freely. All theseparameters are passed to tk_evt_ssy. If the system call is not invoked for any particular resource group, resid can be set to 0.

If processing completes normally, E_OK is passed in the return code; otherwise an error code

(negative value) is returned.

The following event types evttyp are defined. See 5.3 for details.


	#define	TSEVT_SUSPEND_BEGIN	1	/* before suspending device	*/
	#define	TSEVT_SUSPEND_DONE	2	/* after suspending device	*/
	#define	TSEVT_RESUME_BEGIN	3	/* before resuming device	*/
	#define	TSEVT_RESUME_DONE	4	/* after resuming device	*/
	#define	TSEVT_DEVICE_REGIST	5	/* device registration notice	*/
	#define	TSEVT_DEVICE_DELETE	6	/* device deletion notice	*/

An event handling function runs as a quasi-task portion in the context of the task that called tk_evt_ssy.

[Additional Notes]

Extended SVC handlers as well as break functions, startup functions, cleanup functions and event handling functions all have the equivalent of the TA_HLNG attribute only. There is no means of specifying the TA_ASM attribute.

Prior to initialization of a resource control block by a startup function, and after resource release by a cleanup function, the behavior if an extended SVC is called by a task belonging to that resource group is dependent on the subsystem implementation. The OS does not make any attempt to prevent this kind of call. Basically it is necessary to avoid calling an extended SVC before calling a startup function and after calling a cleanup function.

There may be cases where, for some reason or other, a break function, cleanup function or event handling function is called without .rst calling a startup function. These functions must execute normally even in such a case. A resource control block is cleared to 0 when it is .rst created and when cleanup processing is executed by tk_cln_ssy. Accordingly, even if it was not initialized properly by a startup function, the resource control block can still be assumed to have been cleared to 0.

Comments