Ingres CL CS

From Ingres Community Wiki

Jump to: navigation, search

Ingres Compatability Library
Architecture - Overview - Suggestions - GL: BA - BT - ERGL - handy - HSH - LC - LL - MEGL - MM - MO - MU - PM - SP - TMGL - CL: CI - CK - CM - CP - CS - CSMT - CV - CX - DI - DL - DS - ER - ERold - EX - FP - GC - GV - handy - ID - JF - LG - LK - LO - ME - MH - NM - OL - PC - PE - QU - SA - SI - SR - ST - TC - TE - TH - TM - TR - UT

Contents

Compatibility Library Specification – CS

Abstract

This is the specification of the CS facility provided by the compatibility library for server threads. Revision: 2.1, 08-Apr-98

Document History

  • Revision 2.1, 08-Apr-98
    • Added thread_id parameter to CSadd_thread() for 2.1
  • Revision 2.0 , 29-Jul-94. These changes are for 6.5, a/k/a OpenINGRES 1.x.
    • CSfind_scb was missing from the spec, though present and used since events were added in 6.3.
    • A CS 'sid' (Session ID) is the new CS_SID type, not a nat. The CS_SID type may need to be big enough to hold a pointer that is bigger than a longnat. An example is Alpha/OSF with 64 bit pointers. All interfaces taking sids are changed to use it, and CS_ADDER_ID and cs_self are of that type. (10-sep-93)
    • CSmonitor takes a pointer to a TR_FORMAT_FUNC function. (1-may-92).
    • CSsuspend must error on a timeout value < 0. (1-may-92).
    • CSn_semaphore (give it a name) added (1-may-92).
    • CSO_LOCK_CACHE added (1-may-92).
    • CS_SEM_NAME_LEN added (9-oct-92)
    • CSa_semaphore and CSd_semaphore added (9-oct-92).
    • CS_MAXNAME, CS_SCB.cs_username[ size ] should all be GL_MAXNAME. (30-oct-92).
    • CScp_resume and CSms_thread_nap approved (23-jul-93).
    • <csdbms.h> is removed (17-sep-93).
    • CS_OPTIONS in <cs.h> is removed (17-sep-93).
    • CS_INFO_CB in <cs.h> loses cs_multiple, cs_cursors, cs_optcnt and cs_option fields (17-sep-93).
    • argc and argv to CSinitiate are now meaningless (17-sep-93).
  • Revision 1.0 , last modified 4-Oct-91
    • The CS_OPTIONS structure was given the cso_float member, and the values of the defines in <csdbms.h> were removed to indicate that the actual values are system specific. Several new option symbols were added.
    • Typos and other editorial problems were fixed.
    • The description of CSattn was clarified.
    • An explanation of interrupts was added.
    • CS_CONDITIONS were added.
    • Shared CS_SEMAPHORES were removed.
    • CSr_semaphore was added.
    • Correct spelling of CS_ADDER_ID.
    • The cs_client_type member was added to the CS_SCB.
    • The new CS_REMOVE_EVENT was added, and the old CS_NOTIFY_EVENT was mentioned.
    • Added obsolete CSaccept_connect.

Specification

Introduction

This CLF module provides a Control System (CS) for controlling multiple threads of activity within a server. The CS module allows multiple threads of execution to share the machine cycles in a priority-based manner under control of the INGRES system.

The CS module can be easily implemented to support the degenerate case of a single thread of execution in systems which encourage such a model.

Library

CL

Intended Uses

The initial purpose of the CS module is to provide support for multithreading of the DBMS. However, the CS module has been designed so the interface to the module will work equally well with other Ingres applications. Thus, it would be possible to use the CS module to build a multiterminal server for the Ingres frontends.

Assumptions

It is assumed that the notion of a multithreaded server is understood. The CS module provides the capability to support such an object.

It is assumed that the notion of a semaphore is understood. (Reference: Operating Systems, Madnick, Stuart E., & Donovan, John J., McGraw-Hill Book Co., 1974.)

It is assumed that the notion of a condition is understood. (References: An Introduction to Programming with Threads by Andrew D. Birrell (DEC SRC) and Threads Extension for Portable Operating Systems, IEEE P1003.4a)

When CS is providing full services, the CS module assumes that the system provides the following capabilities. Implementation platforms may choose to implement less than a full service CS module.

Timer Based Interrupts The CS module may make use of the system's timers to provide time-sliced execution of threads within a priority. CS does not require the use of time-sliced execution. Implementation platforms may choose not to provide this capability and have all threads "voluntarily" give up the CPU periodically.
Asynchronous Event Completion The CS module provides interface points to allow a thread to suspend itself while awaiting the completion of a system event. Once again, implementation platforms may choose to use polling to determine the completion events in environments where true asynchrony is less convenient.

CS module must occasionally run in a mode during which it is not informed of asynchronous event completion. These periods of time are short, but required if the system supports true asynchronous events.

When the CS module is configured to run in the degenerate case described above, these assumptions can be relaxed.

It is assumed that the remainder of the Compatibility Library and, indeed, of OpenIngres/Jasmine, is modified to use the features provided by the CS module. Alone, the CS module cannot provide full multithreaded server capability. It expects that the other CL modules which interact with the system cooperate with it. This means, primarily, that the other CL modules make the appropriate suspend & resume calls on behalf of the current thread as necessary. For example, the DI module of the CL is expected to be built such that I/O requests inform the system that the resume (CSresume()) routine is to be called at the completion of the I/O, and then the DI module, having requested an asynchronous I/O, should call the suspend routine (CSsuspend()). Thus, DIread() may be coded (details removed for the sake of clarity) as

DIread(...)
{
  preprocessing...
  status_of_queuing =
    system_io_request(parms..., CSresume, session_id);
  if (status_of_queuing != successful)
  {
     process error and return;
   }
   status = CSsuspend(...);
   postprocessing...
}

Definitions and Concepts

Server The address-space inside which threads execute. This may consist of one or more operating system processes.
Thread or Session Interchangeable terms, a schedulable entity within the server address-space. Each has its own stack and program counter.

Overview:

The CS module supports the multithreading of a number of similar threads. The threads all must run the same application code. Applications are specified to the CS module as a set of functions which are called by the CS module to accomplish the work of the application. These functions are specified as pointers to critical entry points in the main application. These entry points are

  • Server initiation
  • Communication routines
    • await thread request
    • reject thread request
    • disconnect threads
    • read thread
    • write thread
    • out-of-band completion
  • Thread processing
  • Server termination
  • Error logging
  • Control block allocation.

Each of these is called in a prescribed manner to perform their various functions.

Threads are added to the server as requested by the users. The method of attaching to the server will vary from system to system. On VAX/VMS systems, users will send a request to public mailbox to request such an action.

As a thread is added to the server, the CS module will add the new thread to its list of known threads. The underlying application will be called to initiate this thread, and operation will proceed as described above. The difference between the multithreaded nature of, say, a VAX/VMS system and the single threaded nature of another system should be entirely hidden within the CS module. There is no reason for the underlying application to behave any differently in these differing systems.

The CS module declares no global variables which are known outside itself. Internally, it may require varying support on each system.

Thread operations

At the time the server is invoked, the specified server initiation routine is called as

   status = (*server_initiation)(&CS_INFO_CB);

This routine is expected to perform whatever initiation is necessary for the server being run.

As new threads are added (via calls to CSresume with the session ID CS_ADDER_ID -- this call is made by the await_thread_request routine, also known as Cs_cb.cs_saddr), the thread processing routine is called

   status = (*thread_processing)(mode_of_operation,
                 &thread_control_block,

&next_mode_of_operation);

where mode_of_operation and next_mode_of_operation are as specified below. Any status != OK results in thread termination.

When reading or writing are necessary,

   status = (*read_routine)(&thread_control_block, sync_boolean)

or

   status = (*write_routine)(&thread_control_block, sync_boolean)

are called. (All communication routines are called using this paradigm.) Status OK here result in normal processing; if read returns E_CS001E_SYNC_COMPLETION, then it is assumed that the read request already completed, and that no thread suspension need take place. Similarly, if write returns E_CS001D_NO_MORE_WRITES, then no suspension for the write needs to take place. Note that the system is optimized on the assumption that the server will do more write's than reads, so the normal control flow is

     if (need to read)
     {
          call read routine
          if status == OK
             suspend
     }
     call processing routine
     if (need to write)
     {
          do
          {
              call write routine
              if status != no more writes
                  suspend
          } while status == OK
     }

When time comes for the server to terminate,

         (*termination_routine)()

is called to allow the system to run itself down as necessary.

Error logging is used to place errors encountered by the CS module into the server error log. Memory allocation is used to allocate and deallocate the thread control blocks which are used by the CS module and by the underlying application. By changing these critical entry points, the underlying application controlled by CS can be changed.

Modes of thread operation:

Threads are called with a mode of operation, which specifies the activity which the thread is expected to perform, and returns with a mode of operation which specifies what activity the thread expects to perform next. The possible modes of operations are:

CS_INITIATE Given to the processing routine to indicate that a new thread is to be initiated. Never returned to the CS module.
CS_INPUT Given to processing routine to indicate that input has been supplied from the user. Returned to the CS module to indicate that more input is needed.
CS_OUTPUT Given to the processing routine to indicate that it is expected to be providing more output (i.e. it last returned CS_OUTPUT). Returned to the CS module to indicate that the CS module should output the supplied buffer and call the processing routine back.
CS_EXCHANGE Never given to a processing routine. Returned to the CS module to indicate that the module should output the supplied buffer, and await an input message from the user.
CS_TERMINATE Given to the processing routine to indicate that it should terminate the current thread. Returned to the CS module to indicate that the thread is to be terminated, and that the CS module should call back the processing routine with the CS_TERMINATE operation code.

At thread initiation time, the thread is called to allow it to perform whatever application specific actions are necessary. After that, the thread sets its mode of operation. Thus, normally, a DBMS thread will return an operation mode of CS_INPUT, to indicate that the user needs to supply a query. Once so supplied, the DBMS will return CS_OUTPUT until the query has been completed, at which point it will return CS_EXCHANGE, to indicate that the output should be sent and that the CS module should then await new input. Once the user sends a termination request, the DBMS would return an operation mode of CS_TERMINATE, with which it will be called back. Returned modes from a called CS_TERMINATE are ignored.

Synchronization:

The CS module provides capabilities for the threads to interact in the sharing of resources in two ways. First, there are semaphores, which when combined with the typical 'p' and 'v' operations allow threads to lock access to software resources. Conditions provide an event mechanism around semaphores, providing a convenient way of programming some operations in ways that avoid deadlock. Semaphores may be used across servers; conditions must be private to a server.

Thread priorities, time slicing, and suspension:

The CS module provides for the prioritized execution of threads within the server. As the server becomes ready to execute a new thread, CS will pick the highest priority thread to execute. Within a priority, the threads are picked in a "round robin" fashion. The scheduler is not currently intended to be preemptive; that is, should a higher priority thread become ready, the lower priority thread will be allowed to either complete its current time quantum (see below) or be suspended when it so volunteers.

The CS module provides for time sliced execution of the threads within a server. The time quantum can be selected by the system administrator at a particular user site. A provision can be made to disable this feature, so that threads will be suspended only while awaiting a system event completion. (On VMS, this is done via the server startup program.) Time slicing may not truly exist in a pre-emptive way. Client calls to CSswitch() are necessary to ensure the appearance of time slicing on systems that do not provide it.

Threads volunteer to be suspended while awaiting the completion of some system event. They may also be suspended while awaiting a semaphore or a condition. Each thread is allowed to be awaiting no more than one regular event or semaphore at a time. A provision is made to allow the thread to be informed of an out-of-band I/O (for interrupts).

Interrupts and Attentions

While running, a thread may be in a number of different states. For example, a thread may be running or suspended. In addition, a thread may receive an asynchronous notification of a "special" event, called an "interrupt" or an "attention." Note that within CS these events within CS are not asynchronous, even though they are called "interrupts" . In particular, CS interrupts have no connection to an EX_INTR exception raised in the process running with CS threads.

Attentions are currently used for the following reasons, which are handed to CSattn as the event type.

CS_ATTN_EVENT To indicate that a "^C" or other terminal exception was received by the thread's associated front-end.
CS_NOTIFY_EVENT something about alerters.
CS_RCVR_EVENT To indicate that the Logging System has requested that a thread's transaction be aborted, either because it is holding up the log file due to its status as the oldest active transaction (Force Abort), or that it has been heuristically aborted by manual means (lartool).
CS_REMOVE_EVENT To indicate that the thread is being forcibly removed.
CS_SHUTDOWN_EVENT To indicate (to a "special" thread (Fast Commit, Write Behind)) that the server is now shutting down

(More "attention" types are planned in the future)

This mechanism requires co-operation between the CS, GC, LG, and LK components of the CL.

The operation of attentions involves the following significant activities:

  • Delivering an attention to a thread.
  • Interrupting the thread's operation.
  • Acknowledging the interrupted operation.
  • Cancelling an unwanted CSresume() call.

The effect of these various operations is described in the following state-transition table, where each row represents a state (defined at the end of the table), and each column represents a possible transition event.

CS Thread State Transitions

Current State 	Event
        SI 	SNI 	Attn 	Ack 	Resume 	Cancel 	Timeout	 
Run 	SI 	SNI 	RunIP 	Run 	RunR 	Run 	N/A	 
RunIP 	Run* 	SNIIP 	RunIP 	Run 	RunRIP 	RunIP 	N/A	 
RunR 	Run 	Run 	RunRIP 	RunR 	ERROR 	Run 	N/A	 
RunRIP RunIP 	RunIP 	RunRIP 	RunR 	ERROR 	RunIP 	N/A	 
_	 	 	 	 	 	 	 	 
Run* 	ERROR 	ERROR 	RunIP* 	Run* 	RunR* 	Run 	N/A	 
RunIP* ERROR 	ERROR 	RunIP* 	Run* 	RunRIP* RunIP 	N/A	 
RunR* 	ERROR 	ERROR 	RunRIP* RunR* 	ERROR 	Run 	N/A	 
RunRIP* ERROR 	ERROR 	RunRIP* RunR* 	ERROR 	RunIP 	N/A	 
_	 	 	 	 	 	 	 	 
Run+ 	ERROR 	ERROR 	RunIP+ 	Run+ 	RunR+ 	Run 	N/A	 
RunIP+ ERROR 	ERROR 	RunIP+ 	Run+ 	RunRIP+ RunIP 	N/A	 
RunR+ ERROR 	ERROR 	RunRIP+ RunR+ 	ERROR 	Run 	N/A	 
RunRIP+ ERROR 	ERROR 	RunRIP+ RunR+ 	ERROR 	RunIP 	N/A	 
_	 	 	 	 	 	 	 	 
SI 	N/A 	N/A 	Run* 	N/A 	Run 	N/A 	Run+	 
SNI 	N/A 	N/A 	SNIIP 	N/A 	Run 	N/A 	Run+	 
SNIIP 	N/A 	N/A 	SNIIP 	N/A 	RunIP 	N/A 	RunIP+	 

State definitions:

Run This is the normal "running" state.
RunIP Running with Interrupt Pending. CSattn() has been called for the thread, and the next interruptible CSsuspend() will return E_CS0008_INTERRUPTED, unless CSintr_ack() is called first.
RunR Running Resumed. This is a common state in which the CSresume() call arrives before the CSsuspend() call. The next CSsuspend() call will arrives before the CSsuspend() call. The next CSsuspend() call will
RunRIP Running Resumed with Interrupt Pending. Both CSresume() and CSattn() have been called for a running thread.
Run* Running, last suspend returned E_CS0008_INTERRUPTED. The thread is required to cancel the outstanding event wait and then call CScancelled() before making its next CSsuspend() call.
RunIP* Running with Interrupt Pending, last suspend returned
RunR* Running Resumed, last suspend returned E_CS0008_INTERRUPTED.
RunRIP* Running Resumed with Interrupt Pending, last suspend returned
Run+ Running, last suspend returned E_CS0009_TIMEOUT. The thread is required to cancel the outstanding event wait and then call CScancelled() before making its next CSsuspend() call. The primary difference between the "*" states and the "+" states is that some clients of CS (in particular, LK), treat them differently.
RunIP+ Running with Interrupt Pending, last suspend returned E_CS0009_TIMEOUT.
RunR+ Running Resumed, last suspend returned E_CS0009_TIMEOUT. If this state is reached internally by LKrequest(), it is handled differently than RunR* is handled.
RunRIP+ Running Resumed with Interrupt Pending, last suspend returned E_CS0009_TIMEOUT.
SI Suspended Interruptible.
SNI Suspended Non-interruptible
SNIIP Suspend Non-interruptible, Interrupt Pending.

Event Definitions:

SI An interruptible CSsuspend() is issued.
SNI A NON-interruptible CSsuspend() is issued.
Attn CSattn() is called.
Ack CSintr_ack() is called.
Resume CSresume() is called
Cancel CScancelled() is called
Timeout CSsuspend times out.

Since an interrupt may be delivered at a time when the thread is not suspended, interrupts are also polled for. If an interrupt is recognized by the polling code (code which checks various "interrupt flags" that are set by the client event handler called by CSattn()), the client will call CSintr_ack() to acknowledge the interrupt so that CS need no longer hold it pending.

Since the CSsuspend/CSresume mechanism requires a precise synchronization of thread suspension and thread resumption, a precise protocol MUST be followed when a thread is interrupted. Or, to put it differently, since in normal processing CSsuspend and CSresume calls are matched one-to-one, and since interrupting a thread unbalances this matching, and since the unmatched CSresume may arrive asynchronously, the CS module must be informed when the possibly unmatched CSresume has been accounted for. This protocol is described in the CScancelled() interface.

A complete understanding of interrupts requires an understanding of the following topics:

  • The "normal control flow" of a thread, typically implemented as a function called CS_setup() in most CLs.
  • Expedited flow message arrival in the GC(a) CL.
  • CSsuspend, CSresume, CSattn, CSintr_ack, and CScancelled in the CS CL.
  • LKevent and LKrequest in the LK CL.
  • LGevent in the LG CL.

A careful review of several existing implementations is recommended for any person attempting to develop a new CL library.

Data Structures:

CS_CB used to define parameters when CS is first set up.
CS_SCB thread control block. This structure is returned to the CS module by the thread control block allocation routine passed into the module. It is expected that the actual thread control block will be larger than that passed here; however, the CS module will use only the CS_SCB portion, and expects that it be at the returned address of the allocated space.
CS_SID A 'session id', used to identify a thread. It is an opaque type used by the CS module to identify sessions. On some systems the CS_SID is the CS_SCB address, suitably coerced. On others, it might be a small value integer thread-id. You can obtain the values for the current thread with CSget_scb() or CSget_sid(). Other CS functions take CS_SID or CS_SCB * arguments. Clients must be sure to hand in the proper type, or chaos may ensue. Given a CS_SID, clients may locate the CS_SCB by calling CSfind_scb(). Given a CS_SCB *, clients will find the CS_SID is in scb->cs_self.
The type used by the implementor must meet the following criteria.
• It must be castable to and from a PTR.
• It must be comparable for equality if cast to (char *).
• It must be assignable and passable by value.
Integer types and pointers meet these requirements. Aggregate types (structures or unions) and floating types do not.
CS_SEMAPHORE is used to control access to shared data structures within the server under software control. The CSw_semaphore() routine is used by client code to prepare a semaphore for use, and CIr_semaphore() is used to delete one. When CSw_semaphore is given the CS_SEM_MULTI modifier, a semaphore may be used to control access to shared data structures in shared memory between multiple processes.
CS_CONDITION is used as the handle for condition operations. It is setup up with CScnd_init(), using CScnd_wait(), CScnd_signal(), and CScnd_broadcast() as operators. CScnd_free(), CScnd_name() and CScnd_get_name() provide housekeeping services. Their use is more fully described under the CS_CONDITION section and with examples in Chapter 3.
CS_INFO_CB is used to hold server-wide parameters.

Possible Futures:

Since the underlying application is fully specified at server startup, the CS module needs to know nothing about how the underlying application works. However, at the moment, the method of communication from the user to/from the server is known by the CS module. In the future, should it be the case that the company decides to build servers from something other than DBMS's, the CS module should be easily converted to the fully generalized model. (This has been done with GCF). It may be desirable for the CS module to allow each thread to run different code. This should not be very difficult.

Header File <cs.h>

The header file <cs.h> must be included before using any of the functions provided. The following data structures and constants are defined for use.

CS_CB - CS request control block

This structure must be supplied to initiate the services of the CS module of the system. It contains the information necessary for the dispatcher to correctly operate the server. This information includes the addresses of routines to call to allocate session or thread control blocks, to deallocate SCB's, and the address of a routine to perform main processing. This routine is always called with a standard parameter interface (see the CSdispatch() routine header for details).

Also included is the adminstrative information needed to operate the server. This is primarily information about the maximum number of sessions to allow, the maximum number of active sessions, and the size of the stack needed for each active session for this type of server.

typedef struct _CS_CB
{
   i4              cs_scnt;            /* Number of sessions */
   i4              cs_ascnt;           /* nbr of active sessions */
   i4            cs_stksize;         /* size of stack in bytes */
   STATUS          (*cs_scballoc)();   /* Routine to allocate SCB's */
   STATUS          (*cs_scbdealloc)(); /* Routine to dealloc  SCB's */
   STATUS          (*cs_saddr)();      /* Routine to await session requests */
   STATUS          (*cs_reject)();     /* how to reject connections */
   STATUS          (*cs_disconnect)(); /* how to dis- connections */
   STATUS          (*cs_read)();       /* Routine to do reads */
   STATUS          (*cs_write)();      /* Routine to do writes */
   STATUS          (*cs_process)();    /* Routine to do major processing */
   STATUS          (*cs_attn)();       /* Routine to process attn calls */
   VOID            (*cs_elog)();       /* Routine to log errors */
   STATUS          (*cs_startup)();    /* startup the server */
   STATUS          (*cs_shutdown)();   /* shutdown the server */
   STATUS          (*cs_format)();     /* format scb's */
#define                 CS_NOCHANGE     -1      /* no change to this parm */
}   CS_CB;

CS_SCB_Q - queue entry for the session control block

This is simply a structure containing the standard queue header element for session control blocks. Building a standard structure for this reduces name space problems as well as guaranteeing correct usage.

typedef struct _CS_SCB_Q
{
   CS_SCB          *cs_q_next;         /* moving forward . . . */
   CS_SCB          *cs_q_prev;         /* as well as backwards */
}   CS_SCB_Q;

CS_SCB - session control block

This block is expected to be allocated at the beginning of the system session control block. That is, when the Cs_cb.cs_scballoc() routine is called, it will return a pointer to the CS_SCB portion of the underlying systems SCB. CS will never use more than this portion. The top portion of this standard header is expected to be filled in by the allocation routine above.

This block is used by the dispatcher to maintain the state of a particular thread. This section is very machine dependent, and is expected to be altered extensively by other environments.

typedef struct _CS_SCB
{
   CS_SCB          *cs_next;           /* forward queue link */
   CS_SCB          *cs_prev;           /* Backward  "     "  */
   i4              cs_length;          /* Length, including portion not seen */
   i2              cs_type;            /* control block type */
#define                 CS_SCB_TYPE     0xABCD  /* make it obvious in dumps */
   i2              cs_s_reserved;      /* used by mem mgmt perhaps */
   i4              cs_l_reserved;
   i4              cs_owner;           /* owner of block */
#define                 CS_IDENT        0xAB0000BA
   i4              cs_tag;             /* to look for in a dump (ick) */
#define                 CS_TAG          'cscb'
   CS_SID          cs_self;            /* session id for this session */
#define                 CS_DONT_CARE        ((CS_SID)0x0)
#define                 CS_ADDER_ID         ((CS_SID)0x1)
/*   -  -   -   -   -   -   -   -   -   -   -   -   -   -   -   -   */
   /*
   ** This section is very heavily machine specific.  It is placed near the
   ** top to reduce offsets and thus to reduce code space.
   */
   i4              cs_psl;             /* VAX Processor status longword */
   i4              cs_registers[16];   /* VAX register set */
#define                 CS_VAX_RO       0
#define                 CS_VAX_R1       1
#define                 CS_VAX_R2       2
#define                 CS_VAX_R3       3
#define                 CS_VAX_R4       4
#define                 CS_VAX_R5       5
#define                 CS_VAX_R6       6
#define                 CS_VAX_R7       7
#define                 CS_VAX_R8       8
#define                 CS_VAX_R9       9
#define                 CS_VAX_R10      10
#define                 CS_VAX_R11      11
#define                 CS_VAX_AP       12
#define                 CS_VAX_FP       13
#define                 CS_VAX_SP       14
#define                 CS_VAX_PC       15
/*  -   -   -   -   -   -   -   -   -   -   -   -   -   -   -   -   */
   I4 	    cs_client_type;	/* for clients, 0 in CL CS_SCBs */
   char            *cs_stk_area;       /* Ptr to allocated stack base */
   i4              cs_stk_size;        /* Amt of space allocated there */
   i4              cs_state;           /* Thread state */
#define                 CS_FREE         0x0000
#define                 CS_COMPUTABLE   0x0001
#define                 CS_EVENT_WAIT   0x0002
#define                 CS_MUTEX        0x0003
#define                 CS_STACK_WAIT   0x0004
#define                 CS_UWAIT        0x0005
   i4              cs_mask;
#define                 CS_TIMEOUT_MASK     0x0001  /* timeout can happen */
#define                 CS_INTERRUPT_MASK   0x0002  /* interrupts are allowed */
#define                 CS_BAD_STACK_MASK   0x0004  /* thread trashed stack once */
#define                 CS_DEAD_MASK        0x0040  /* Thread is doomed */
#define                 CS_IRPENDING_MASK   0x0080  /* interrupt is pending */
#define                 CS_NOXACT_MASK      0x0100  /* thread not in xact */
#define                 CS_MNTR_MASK        0x0200  /* job is a monitor */
#define                 CS_FATAL_MASK       0x0400  /* thread has fatal error */
#define                 CS_ABORTED_MASK     0x0800  /* request aborted */
b#define                 CS_MID_QUANTUM_MASK 0x1000  /* job start mid quantum */
#define                 CS_EDONE_MASK       0x2000  /* Event has completed */
#define                 CS_IRCV_MASK        0x4000  /* Job recieved an intrpt */
#define                 CS_TO_MASK          0x8000  /* Job has timed out */
    i4              cs_priority;        /* Priority of thread */
    i4              cs_base_priority;  /* base priority */
#define                 CS_LIM_PRIORITY 16
   i4              cs_thread_type;     /* type of thread */
#define                 CS_USER_THREAD  0	    /* regular client thread */
#define                 CS_INTRNL_THREAD (-1)	    /* thread used by CS */
   i4              cs_timeout;         /* timeout while waiting */
   i4              cs_sem_count;       /* number of semaphores owned here */
   CS_SCB_Q        cs_rw_q;            /* next on the ready or wait que */
   CS_SEMAPHORE    *cs_sm_root;        /* root for smphr list for this scb */
   CS_SCB          *cs_sm_next;        /* next scb in smphr list */
   i4              cs_mode;            /* what's up now */
   i4              cs_nmode;           /* what's up next */
   i4              cs_uic;             /* UIC of session owner */
   i4              cs_cputime;         /* cputime of this thread */
   i4              cs_dio;             /* disk io count */
   i4              cs_bio;             /* fe/dbms comm count */
   i4              cs_locks;           /* number of locks */
   i4              cs_memory;          /* amount of memory used */
   i4              cs_connect;         /* time in seconds of connection */
   PTR             cs_svcb;            /* server control block addr */
   i4              cs_ppid;            /* parent process if interested */
   char            cs_username[ GL_MAXNAME ]; /* user owning this session */
};

CSattn event types

The following definitions are to be used as event type arguments to CSattn . See the discussion about interrupts and attentions in the introduction.

CS_ATTN_EVENT The user has requested an interrupt of the current operation through the GCA_ATTENTION mechanism of GCF. The completion routine for the GCA Expedited Receive calls CSattn(CS_ATTN_EVENT,...).
CS_NOTIFY_EVENT something to do with alerters. ???
CS_RCVR_EVENT This event can be raised for either of two reasons:
• The Logging System has detected that the log file has become full and has selected the oldest active transaction as a victim.
• A (sufficiently privileged) user (possibly using the 'lartool' utility) is requesting that a transaction be forcibly aborted.
The Logging System calls the server's Force Abort handler, which in turn calls CSattn(CS_RCVR_EVENT,...).
CS_REMOVE_EVENT Someone wants to remove the thread, so it should be interrupted and given a chance to die. For instance, if a session is executing a five-way cartesian product, it will optimize almost forvever (!?). If an administrator wishes to remove the thread (using IIMONITOR), the CSremove will not do anything until the thread finishes the optimization unless it is interrupted.
CS_SHUTDOWN_EVENT: The server is being shutdown through the iimonitor utility. The 'set server shut' command of the iimonitor utility invokes CSterminate() with the CS_START_CLOSE argument once all user threads have exited. Each remaining thread, which is a specialized server thread such as the Fast Commit or Write Behind thread, is interrupted with the CS_SHUTDOWN_EVENT by CSterminate().

Attention event categories

These are event scopes to be or-ed into the event type above when CSattn is called.

CS_THREAD_EVENT The event applied to a single thread.
CS_SERVER_EVENT The event applies to an entire server. Server events are unimplemented and may not be used.

CS_SEMAPHORE - semaphore object

This structure is manipulated by the CS module semaphore manipulation routines to control the internal concurrency on software objects. The structure itself maintains a list of those sessions who are waiting for the semaphore. Thus trashing a semaphore will probably bring down the entire server. CS_SEMAPHORES must be initialized with calls to CSw_semaphore . All semaphores should be given a name with CSw_semaphore. This makes debugging much easier. When the process is done with a semaphore, it must call CSr_semaphore to free any resources that might be associated with it. Also the instance of the semaphore will be removed from the MO splay trees.

A process other than the one that called CSw_semaphore that wants to use a a CS_MULTI semaphore must call CSa_semaphore to attach it. It should call CSd_semaphore to detach it when exiting.

Historically, the init/remove, attach/detach and name operations were added after the early releases of INGRES 6.X. Sometimes they are not used correctly. This causes resource leaks and makes the installation hard to debug, monitor, and manage.

Below, the structure used in the VMS implementation of CS is shown. Note that this structure may NOT be the same on other implementations. Therefore, client code should NOT examine members of the structure directly, nor should client code make any assumptions about the size of this structure.

typedef struct _CS_SEMAPHORE
{
   i2              cs_value;           /* The current value of the semaphore */
   i2              cs_count;           /* number of folks
                                       ** sharing this semaphore
                                       ** By convention, when this number is,
                                       ** negative, the semaphore is held
                                       ** exclusively
                                       */
   CS_SCB          *cs_owner;          /* the owner of the semaphore */
   CS_SCB          *cs_next;           /* those folks awaiting this one */
   CS_SEMAPHORE    *cs_list;           /* list of sem's owned */
};

CS_CONDITION - condition waiting object

A CS_CONDITION is a construct useful for waiting on software objects. A condition differs from a semaphore in that it has different semantics which avoid deadlock problems when protection is needed for a member of a pool of objects which is protected by another semaphore. Conditions together with an exclusive semaphore form a monitor as first described by C.A.R. Hoare. See "An Introduction to Programming with Threads" by Andrew D. Birrell (DEC SRC) and the draft standard "Threads Extension for Portable Operating Systems" , IEEE P1003.4a.

Note that a CS_CONDITION may only be accessed by sessions which are members of the same server (that is, they must all have been created by the same caller of CSadd_thread() ). Sessions in a different server may NOT share this CS_CONDITION. Therefore, CS_CONDITION structures probably should NOT be placed in system-wide shared memory; rather, they should be located in memory which is visible only to the sessions in this server.

A condition structure is used as a descriptor to wait upon for an event which will be later signaled by another session. Typically, the condition structure will contain a queue of sessions waiting upon the condition to be signaled.

When a condition is signaled, a single thread waiting on that condition will be made runnable again. Typical use of a condition is that a session which holds a semaphore finds it must wait for some other session to do work. This can happen with an object pool manager which allows objects to exist in the pool while they are being constructed. For example, if one session is building a plan which other sessions want to use, the sessions which want to use the plan can wait on a condition structure until the plan is built and they are signaled to go ahead. When waiting on a condition, the same semaphore should be specified on each wait. (i.e. a semaphore can be associated with several conditions, but a condition can be associated with only one semaphore.) There is no advantage to using a cross-process semaphore (that is, a semaphore of type CS_SEM_MULTI) with a CS_CONDITION. While some current implementations of CS may allow this, it is not recommended and CS clients should NOT use cross-process semaphores with CS_CONDITION's.

The inside of a CS_CONDITION is not visible to the client.

Definition:

typedef struct _CS_CONDITION
{
	/* contents unknown */
	. . .
} CS_CONDITION;

CS_OPTIONS - server startup parameter block

The CS_OPTIONS block was removed on 17-Sep-94 when option handling was changed to use PM symbols instead of command line parameters.

CS_INFO_CB - server information block

This block is passed to the server startup function to inform the server of various values in which it may be interested.

Typically, these values are set by passing runtime "command line" parameters to the server through the use of a system-specific interface such as the iirundbms program. The CL then must store these runtime parameter values in the CS_INFO_CB structure in order to make them available to the client code.

Currently, client code stores address of these variables in client data structures; therefore, the CS_INFO_CB structure which is passed to the server startup function must remain allocated and referenceable as long as the server remains up. The CL implementation must NOT attempt to free this storage after the server startup function returns.

The cs_mem_sem field must be filled in by the cs_startup routine passed to CS by CSinitiate. The value must be a pointer to the semaphore which generic server code uses to protect calls to MEget_pages, MEfree_pages, and MEprot_pages. Note that the INGRES_THREAD system is not active until the cs_startup routine returns to CS, and therefore generic server code should not protect calls to the ME routines until the cs_startup routine returns to CS.

typedef struct _CS_INFO_CB
{
   i4              cs_scnt;            /* Session count */
   i4              cs_ascnt;           /* active session count */
   i4              cs_min_priority;    /* Min priority for server thread */
   i4              cs_max_priority;    /* Max priority for server thread */
   i4              cs_norm_priority;   /* Priority used for user sessions */
   char            cs_name[16];        /* name of the server */
   PTR             cs_svcb;            /* filled in by initiation */
   CS_SEMAPHORE    *cs_mem_sem;	/* filled in by the cs_startup */


}   CS_INFO_CB;

Header file <csdbms.h>

This file was made obsolete and removed on 17-Sep-94 in a major revamp of startup option handling. It is now done using PM symbols.

Executable Interface

The following functions are provided.

CSaccept_connect - obsolete, kept for compatibility

This interface was added for late INGRES 6.1 but never made it into the spec. It was made obsolete by changes made in 6.4. Existing callers are in error, and should be removed. When this is done, this call will be deleted from the specification.

May be implemented as:

# define CSaccept_connect	(TRUE)

Which ought to reveal callers (and problems of removal) quickly.

CSadd_thread - Add a thread to the server space

This routine is called to add a thread to the server known thread list. The thread is created, placed in the ready queue at the appropriate priority, and is placed in competition for resources.

This routine should allocate a Session Control Block for use by the thread by calling the client's "scb allocator," whose address was passed to CSinitiate in the "cs_scballoc" field of the CS_CB.

This routine performs queue manipulation functions, and, therefore, must run in such a manner as to not be interrupted.

Inputs:

priority Priority for new thread. A value of zero (0) indicates that "normal" priority is to be used.
crb A pointer to the connection request block for the thread. This is the block which was sent to request that a new thread be added. This is a buffer that was passed to (*cs_saddr)() and is provided to the scb allocator for transfer of interesting information to the newly created scb. Note that all current CL implementations magically know the size of this buffer.
thread_type Value by which caller can specify to the thread initiate code what the function of the thread is. A type of zero indicates a normal user thread (this is the type value that CS uses when it wants to add a new user). The meaning of any other values is coordinated between the add_thread caller and SCF.

Outputs:

thread_id The CS_SID thread id associated with this thread.
error Filled with system specific error if appropriate.

Returns:

OK if operation succeeded, otherwise system specific error status.
E_CS0002_SCB_ALLOC_FAIL Unable to allocate scb for new thread
E_CS0004_BAD_PARAMETER Invalid value for priority
E_CS000E_SESSION_LIMIT Too many threads have been requested

Definition:

STATUS
CSadd_thread(
            i4             priority,
            PTR            crb,
            i4             thread_type,
            CS_SID         thread_id,
            CL_ERR_DESC    *error )

CSalter - Alter server operational characteristics

This routine accepts the same CS_CB block passed to CSinitiate(). The arguments passed in here replace those specified to CSinitiate. Only non-procedure arguments can be specified; the processing routine, scb allocation and deallocation, and error logging routines cannot be altered.

Arguments are left unchanged by specifying the value CS_NOCHANGE. Values other than CS_NOCHANGE will be assumed as intending to replace the value currently in force.

Inputs:

ccb The call control block, with
s_scnt Number of threads allowed
s_ascnt Number of active threads allowed
s_stksize Size of stacks in bytes
All other fields are ignored.

Outputs:

None

Returns:

OK if operation succeeded, otherwise system specific error status.
E_CS0004_BAD_PARAMETER

Definition:

STATUS
CSalter(ccb)
CS_CB              *ccb;

CSaltr_session - Alter CS characteristics of session

This routine is called to alter some characteristic of a particular server thread.

If 'session_id' is specified (non-zero) then that indicates the session to alter. If 'session_id' is zero, then the current session (the one from which the call is made) is altered.

Session Alter Options include:

CS_AS_CPUSTATS Turn CPU statistics collecting ON/OFF for the specified session.

Item points to a value of type 'i4'.

If the value pointed at by the parameter 'item' (*(i4 *)item) is zero, CS will no longer collect CPU statistics for the specified session, and any calls to CSstatistics by that session will return a cpu time of zero. If the value pointed at by the parameter 'item' is non-zero, then CS will begin (continue) to keep track of cpu time accumulated by that session.

If the CS_AS_CPUSTATS request is to turn on CPU collecting and this option is already enabled for this thread, then the return value E_CS001F_CPUSTATS_WASSET is returned.

Inputs:

session_id session to alter (zero indicates current session)
option alter option - one of following: CS_AS_CPUSTATS - turn ON/OFF collecting of CPU stats.
item pointer to value used to alter session characteristic. Meaning is specific to each alter option.

Outputs:

None

Returns:

OK if operation succeeded, otherwise system specific error status.
E_CS0004_BAD_PARAMETER Invalid parameter passed.
E_CS001F_CPUSTATS_WASSET Cpu statistics already being collected.

Definition:

STATUS
CSaltr_session( CS_SID          session_id,
   	    	i4              option,
   	    	PTR             item );

CSattn - Indicate async event to CS thread or server

This routine is called to indicate that an unexpected asynchronous event has occurred, and that the CS module should take the appropriate action. This is typically used in indicate that a user interrupt has occurred, but may be used for other purposes.

This routine expects to be called in such a way so that it will run to completion without blocking and without being pre-empted. This is because it manipulates the server session lists and if switched out may leave them in an inconsistent state. Furthermore, this routine must ensure that the thread which is being interrupted does not begin to run until the client's async event handler has run to completion. See the section on Interrupts in the introduction for global interactions involving this routine, particularly the state table.

CSattn() must take different actions depending on the current state of the thread which is to be interrupted:

  • If the thread in question has been suspended, and if the CSsuspend call specified that the suspension was interruptible, the thread should now be resumed with 'interrupted' completion status. Before the thread actually begins running, however, the client code's async event handler should be called. The address of the handler was passed to CSinitiate in the "cs_attn" field of the CS_CB.
  • If the thread in question has been suspended, and if the CSsuspend call did NOT specify that the suspension was interruptible, then the thread cannot yet be resumed, and the interrupt status must be held pending. The client's async event handler is still called.
  • If the thread in question is not currently suspended, then the interrupt status must be held pending.

The client's async event handler is still called.

If the client's async event handler returns a non-zero status, then the interrupt has been acknowledged, and it no longer need be held pending if the thread was non-interruptible.

Inputs:

eid Event identifier. This identifies the event type and event category of the event (only event type is currently used.) The event type is one of the following:
CS_REMOVE_EVENT CSmonitor is removing the thread, so it should be interrupted and told to die.
CS_ATTN_EVENT The user has requested an interrupt of the current operation through the GCA_ATTENTION mechanism of GCF. The completion routine for the GCA Expedited Receive calls CSattn(CS_ATTN_EVENT,...).
CS_RCVR_EVENT This event can be raised for either of two reasons:
• The Logging System has detected that the log file has become full and has selected the oldest active transaction as a victim.
• A (sufficiently privileged) user has used the 'lartool' utility to request that a transaction be forcibly aborted. The Logging System calls the server's Force Abort handler, which in turn calls CSattn(CS_RCVR_EVENT,...).
CS_SHUTDOWN_EVENT: The server is being shutdown through the 'iimonitor' utility. The 'set server shut' command of the iimonitor utility invokes CSterminate() with the CS_START_CLOSE argument once all user threads have exited. Each remaining thread, which is a specialized server thread such as the Fast Commit or Write Behind thread, is interrupted with the CS_SHUTDOWN_EVENT by CSterminate().
The event category must be masked in as either of:
CS_THREAD_EVENT The event applied to a single thread.
CS_SERVER_EVENT The event applies to an entire server. Server events are unimplemented and may not be used.
sid Thread id for which the event occurred. If the CS_SERVER_EVENT flag is set in 'eid' then this event is intended for the server, in which case this parameter should be zero (0).

Outputs:

None

Returns:

None

Side Effects:

The indicated thread is interrupted and will begin running again.

Definition:

VOID
CSattn( i4                 eid, 
   	CS_SID             sid );

CSa_semaphore - attach to a CS_MULTI semaphore

This process is going to be using the semaphore. Side effects may include making the semaphore visible to management facilities (eg: MO), or executing system-specific actions allowing use of a native semaphore. Because of this, a semaphore that has been attached must be detached with a CSd_semaphore() call when no longer needed.

Attaching a CS_SEMAPHORE that was initialized as CS_SEM_SINGLE is a no-op; nothing happens. (It was made visible to monitors with the CSw_semaphore call if needed.)

Attaching a CS_SEM_MULTI semaphore that was initialized in this process is also a harmless no-op. It is improper to call CSp_semaphore or CSv_semaphore in a process that did not initialize it unless this routine has been called without a subsequent detach. It is unspecified whether P and V semaphore will attempt to check this.

Inputs:

sem the semaphore in question

Outputs:

none

Returns:

OK if the operation succeeded
other reportable error status.

Side Effects:

May make the semaphore known to management facilities.

Definition:

STATUS CSa_semaphore( CS_SEMAPHORE *sem );

CScancelled - Event has been canceled

This routine is called by the client routines when an event for which the client had suspended will not be CSresume()'d in the future (it may have already been). This call is intended to be used whenever a CSsuspend() returns an interrupted or timed out status. In these cases, on some systems, the CSresume() call may appear in the future, because, for example, the event occurred just after the timeout value has expired. In this case, the dispatcher's scheduler cannot tell which event has completed, and if it is not told when a sequence is complete, the dispatcher cannot determine when a thread can be resumed correctly.

Thus, it must be the case that if a CSsuspend() routine returns anything other than OK (i.e. that the event completed normally), than a CScancelled() call must occur before the next CSsuspend() call is made. And furthermore, the CScancelled() call indicates that the CSresume() call which was queued previously will not occur (it may have already, or it may never occur, but it may not occur after the CSresume() call is made).

See the section on Interrupts in the introduction for global interactions involving this routine, particularly the state table.

Inputs:

ecb Pointer to a system specific event control block. Can be zero if not used.

Outputs:

None

Returns:

None

Definition:

VOID
CScancelled(ecb)
PTR             ecb;

CScnd_broadcast - wake all waiters on a condition

Set runable all waiters on the condition.

Inputs:

cond CS_CONDITION to wake up.

Outputs:

None

Returns:

OK if operation succeeded, otherwise system specific error status.

Side Effects:

The woken sessions will reacquire a semaphore. Typically, the signaler will hold that semaphore when signaling so the woken threads will not really run until the semaphore is released. And then they will run only as the semaphore becomes available. See examples.

Definition:

STATUS
CScnd_broadcast(cond)
CS_CONDITION	*cond;

CScnd_free - free condition object

Release any internal state or objects related to the condition Note that the condition object should not be used again unless re-initialized.

Inputs:

cond CS_CONDITION to free

Outputs:

None

Returns:

OK if operation succeeded, otherwise system specific error status. (Possibly due to freeing a condition on which some other session is waiting.)

Definition:

STATUS
CScnd_free(cond)
CS_CONDITION	*cond;

CScnd_get_name - get the name bound to a CS_CONDITION

Return the name which may have been bound to the CS_CONDITION.

Inputs:

cond CS_CONDITION whose name is requested.

Outputs:

None

Returns:

NULL No name has been bound
pointer to string, the name previously set.

Definition:

char	*
CScnd_get_name(cond)
CS_CONDITION	*cond;

CScnd_init - initialize condition object

Prepare a CS_CONDITION for use.

Inputs:

cond CS_CONDITION to prepare

Outputs:

cond Prepared CS_CONDITION

Returns:

OK if operation succeeded, otherwise system specific error status.

Definition:

STATUS
CScnd_init(cond)
CS_CONDITION	*cond;

CScnd_name - bind a name to a CS_CONDITION

Attach a name to a CS_CONDITION for debugging and monitoring uses.

Inputs:

cond CS_CONDITION to name
name String containing name. The space for the string must be left until a subsequent CScnd_name or a CScnd_free.

Outputs:

None

Returns:

OK if operation succeeded, otherwise system specific error status.

Side Effects:

The CL may register the condition with a monitoring service not part of CS.

Definition:

STATUS
CScnd_name(cond, name)
CS_CONDITION	*cond;
char		*name;

CScnd_signal - condition signal

Signal that at least one waiter on the condition should be set runable.

Inputs:

cond CS_CONDITION to wake up.

Outputs:

None

Returns:

OK if operation succeeded, otherwise system specific error status.

Side Effects:

The woken session will reacquire a semaphore. Typically, the signaler will hold that semaphore when signaling so the woken thread will not really run until the semaphore is released. See examples.

Definition:

STATUS
CScnd_signal(cond)
CS_CONDITION	*cond;

CScnd_wait - condition wait

Wait for a condition to be signaled, releasing a semaphore while waiting and getting the semaphore again once woken. Users of CScnd_wait must be prepared for CScnd_wait to return without the condition actually being met. Typical use will be the body of a while statement which performs the actual resource check.

A CScnd_wait may return even when the condition is not met. CScnd_wait may even return without being signaled to wake a waiter. This requires the user to check that whatever the session is waiting for has happened.

When waiting on a condition, the same semaphore should be specified on each wait. (i.e. a semaphore can be associated with several conditions, but a condition can be associated with only one semaphore.)

Internally to CScnd_wait, a session may be in either of two wait states:

1. waiting for the condition to be signalled or broadcast, and 2. waiting to re-acquire the semaphore.

These two wait states should be distinguished by CS, so that users of CS (such as iimonitor) can identify in which state a session is currently blocked.

Inputs:

cond CS_CONDITION to wait upon.
semaphore CS_SEMAPHORE to release while waiting

Outputs:

semaphore CS_SEMAPHORE released and reacquired

Returns:

OK if operation succeeded, otherwise system specific error status.
E_CS000F_REQUEST_ABORTED Thread was removed during the wait The semaphore will not be reacquired

Side Effects:

The semaphore must be released atomically with the wait upon the condition and reacquired before normal return.

Definition:

STATUS
CScnd_wait(cond, semaphore)
CS_CONDITION	*cond;
CS_SEMAPHORE	*semaphore;

CScp_resume - Resume (a thread in) a process

This routine resumes the indicated thread in the indicated process.

If the indicated process is this process, then this is a simple CSresume operation. If the indicated process is another process, then that process must be notified that it should CSresume the indicated thread.

If the indicated process is not a multi-threaded process, then the value of 'sid' which will be passed is the value returned from CSget_sid when called in the target process.

Usage: This routine is used by server code.

Threads and processes in the server portion of an installation co-ordinate their activity using this routine. Threads and processes which use this routine typically advertise their process ID's and thread ID's in shared memory. Thus a thread which must await the occurrence of a certain event might:

  • find its own process ID and thread ID by calling PCpid() and CSget_sid().
  • place itself on a list of agents awaiting the event, storing its process ID and thread ID in that list.
  • call CSsuspend() to await the event. Then, when the event occurs, some other agent in the installation traverses the list of waiters, and calls CScp_resume to awaken the waiters.

Inputs:

pid the indicated process
sid the indicated session

Outputs:

None

Returns:

VOID

Definition:

VOID CScp_resume( PID pid, i4  sid );

CSdispatch - Begin multi-user operation

This routine is called to actually begin the operation of the server. It is separated from CSinitiate() so that the server code can regain control in the middle to perform any logging or runtime initialization which it desires to do, or to allow the initiate code to be called once while dispatch is called repeatedly as is the case in some environments.

The routine operates as follows. First the dispatcher begins to initialize itself to be ready to add threads. It builds session control blocks for the dispatcher special threads (if any). At the moment, this is limited to the administrative thread, which is used to start and stop threads, and the idle thread (also called idle job), which is run when no other threads are runnable.

When the dispatcher is ready to accept addthread requests, it calls the user supplied initialize server routine. The address of this routine was provided to CSinitiate in the cs_startup field of the CS_CB. This routine takes one parameter, which is the address of a CS_INFO_CB structure which has been properly initialized with values provided to the server when it was started. It is assumed that a non-zero return indicates failure. In the event of failure, the error returned is logged, along with the a message indicating failure to start up. Then the user supplied termination routine is called, thus allowing any necessary cleanup to occur.

If the initiation routine succeeds (i.e. returns OK), then the client code's thread request routine is called to notify the communications subsystem that thread requests from frontend programs may now begin. This routine, whose address was passed in the cs_saddr field of the CS_CB to CSinitiate, takes 2 parameters: the address of a sufficiently large buffer for client code to store thread requests in, and a 'sync' argument -- 1 if synchronous, 0 otherwise.

The dispatcher then begins operation by causing the idle job to be resumed. The idle job is a thread like any other which operates at a low priority, sleeping when the server has nothing else to do. If the dispatcher/idle thread notices that something nasty has occurred, then it will break out of its normal operational loop. Here, there is nothing to do but shutdown, so the user supplied shutdown routine is called, and a message logged that the server is dying off. Then, the exit handler is deleted and the process exits.

Inputs:

None

Outputs:

None

Returns:

Never, under normal circumstances. Should a call be made to CSdispatch() before the required call to CSinitiate() is made, an E_CS0005_NO_INITIATE is returned.

Definition:

STATUS
CSdispatch()

CSdump_statistics - Dump CS statistics

This call is used to dump the statistics collected by the CS system. It is intended to be used for performance monitoring and tuning.

Since there are no external requirements for what server statistics are gathered by CS, the amount of information dumped by this routine is totally dependent on what particular statistics are kept by this version of CS. Therefore, no mainline code should make any assumptions about the information (if any) dumped by this routine.

This function will format text into a memory buffer and then use a caller provided function to dispose of the buffer contents. The caller may pass in TRdisplay as the print function in order to set the output to the server trace file.

The print function is called like:

(*fcn)(buffer);

where buffer will be a null-terminated character string.

Inputs:

print_fcn function to call to print the statistics information.

Outputs:

None

Returns:

None

Side Effects:

The print function is called many times to output character buffers. Whatever side effects the caller-supplied print_fcn has.

Definition:

VOID
CSdump_statistics(print_fcn)
i4          (*print_fcn)();

CSd_semaphore - detach from multi-process semaphore

This process is not going to be using the semaphore anymore. Side effects may include making the semaphore invisible to management facilities (eg: MO), or executing system-specific actions denying use of a native semaphore.

Detaching a CS_SEM_SINGLE semaphore is a harmless no-op. It will be detached by calling CSr_semaphore.

It is an error to detach a CS_SEM_SINGLE semaphore that has not been previously attached.

Inputs:

sem the semaphore in question

Outputs:

none

Returns:

OK if the operation succeeded
other reportable error status.

Side Effects:

May make the semaphore known to management facilities.

Definition:

STATUS CSd_semaphore( CS_SEMAPHORE *sem );

CSfind_scb - Get the current scb

This routine is called by one thread to find the session cb (CS_SCB) of another thread.

Many CS implementations use "hardware hashing" of thread ids (the thread id is the address of CS_SCB). In this case the routine will just return it's argument, suitably coerced. If the sid is a small-integer, the routine will need to locate the CS_SCB in some other fashion (index into a thread table, or search through a list) and return the address.

It is assumed that the caller has permission to access any other thread in the server. Once the CB is returned to the caller the caller should make sure they're not fiddling with a session that's about to evaporate the data structures that are being accessed.

If the session ID does not correspond to an active thread then NULL is returned. It is up to the caller to verify that a non-NULL session CB was returned. It is not an internal CL error to pass in an invalid session ID, but caller will be notified through a NULL session CB.

Inputs:

sid Known thread id for which we want the corresponding session SCB.

Outputs:

None

Returns:

CS_SCB Pointer to session CB or NULL if active session CB was not found.

Definition:

CS_SCB*CSfind_scb( CS_SID sid );

CSget_scb - Get the current scb

This routine returns a pointer to the current scb.

This routine may not return a null scb pointer. It is the responsibility of the CS module to ensure that this routine never returns a null scb pointer. In particular, the CS module must ensure that there exists a current scb (the idle thread can be used if no other thread is running) once CSdispatch has been called (i.e., before the mainline server startup routine is run). CSget_scb may NOT be called before CSdispatch is called, nor may CSget_scb be called from client code which is run 'out of thread context' (such as GC completion handlers).

Inputs:

None

Outputs:

*scbptr thread control block pointer.

Returns:

None

Definition:

VOID
CSget_scb(scbptr)
CS_SCB      	   **scb_ptr;

CSget_scb - Get the current scb

This routine returns a pointer to the current scb.

This routine may not return a null scb pointer. It is the responsibility of the CS module to ensure that this routine never returns a null scb pointer. In particular, the CS module must ensure that there exists a current scb (the idle thread can be used if no other thread is running) once CSdispatch has been called (i.e., before the mainline server startup routine is run). CSget_scb may NOT be called before CSdispatch is called, nor may CSget_scb be called from client code which is run 'out of thread context' (such as GC completion handlers).

Inputs:

None

Outputs:

*scbptr thread control block pointer.

Returns:

None

Definition:

VOID
CSget_scb(scbptr)
CS_SCB      	   **scb_ptr;

CSget_sid - Get the current thread id

This routine returns the current thread id.

Inputs:

None

Outputs:

*sidptr thread id.

Returns:

None

Definition:

VOID
CSget_sid( CS_SID *sidptr );

CSinitiate - Initialize the CS and prepare for operation

This routine is called at system startup time to allow the CS module to initialize itself, and to allow the calling code to provide the appropriate personality information to the module.

CSinitiate is passed three arguments. The first two arguments are the addressed of the argument count and argument vector from the system startup command line or host calling environment. The third argument provides the personality information for the server. This personality information is provided as a pointer to a CS_CB structure. This structure contains personality information including the size of the server in terms of number of allowable threads, the size and number of stacks to be partitioned amongst the threads, and the addresses of the routines to be called to allocate needed resources and perform the desired work. (The calling sequences for these routines are described in the "Definition/Concepts" section of the CS specification.)

If all three of the arguments to CSinitiate are zero, the system is initialized to allow for standalone programs which may use CL components which call CS to operate. In these standalone programs, CSinitiate may also be called more than once; subsequent calls to CSinitiate should be treated as no-ops and should NOT cause an error status to be returned.

When CSinitiate is called with a non-NULL ccb, then MEadvise should have been called with ME_INGRES_THREAD_ALLOC. When running in a threaded process, calls to certain ME routines need to be protected from re-entrancy by locking the semaphores provided in the csib.cs_mem_sem parameter.

Also see:

CS_INFO_CB and ME for discussion of semaphore use to protect memory allocation when running multithreaded.

Inputs:

argc Ptr to argument count for host call
argv Ptr to argument vector from host call
ccb Call control block, of which the following fields are interesting
s_scnt Number of threads allowed
s_ascnt Number of active threads allowed
s_stksize Size of stacks in bytes
s_shutdown Server shutdown function
rv = (*cs_shutdown)();
s_startup Server startup function
'rv = (*cs_startup)(&csib);' where csib has the following fields
csib.cs_scnt connected threads
csib.cs_ascnt active threads
csib.cs_multiple are objects in this server served by multiple servers
csib.cs_cursors Number of cursors per thread allowed
csib.cs_min_priority minimum priority a CS client can start a thread with.
csib.cs_max_priority maximum priority a CS client can start a thread with.
csib.cs_norm_priority default priority for a session if no priority is specified at startup time.
csib.cs_optcnt number of options
csib.cs_option array of option blocks describing application specific options.
csib.cs_cs_name is expected to be filled with the server name.
s_scballoc Routine to allocate SCB's
rv = (*cs_scballoc)(&scbptr, buffer); where buffer is that filled by
(*cs_saddr)() scb->cs_username is expected to be filled with the name of the invoking user.
s_scbdealloc Routine to dealloc SCB's
rv = (*cs_scbdealloc)(&scb);
s_elog Routine to log errors
rv = (*cs_elog)(internal error, &system_error, p1_length, &p1_value, ...);
s_process Routine to do major processing
rv = (*cs_process)(mode, &scb, &next_mode); where mode and next_mode are one of CS_INITIATE, CS_INPUT, CS_OUTPUT, CS_EXCHANGE, or CS_TERMINATE, and next_mode is filled by the callee.
s_attn Routine to call to handle async events
(*cs_attn)(event_type, scb for event)
s_format Routine to call to format scb's for monitor
(*cs_format)(&scb,iimonitor_command_line);
s_read Routine to call to get input
(*cs_read)(scb, sync) where here and below, the <sync> parameter indicates whether the service should operate synchronously or not. If not, then the caller will suspend, unless otherwise noted.
s_write Routine to call to place output
(*cs_write)(scb, sync) Will be called repeatedly as long as it continues to return OK. To normally terminate the writing, return E_CS001D_NO_MORE_WRITES. (This assumes users ``ask short questions requiring long answers.)
s_saddr Routine to call to request threads.
(*cs_saddr)(buffer, sync)
s_reject Routine to call to reject threads.
(*cs_reject)(buffer, sync) where buffer is that used on the previous (*cs_saddr)() call.
s_disconnect Routine to call to disconnect communications with partner.
(*cs_disconnect)(scb)

Outputs:

None

Returns:

OK if operation succeeded, otherwise system specific error status.

Definition:

STATUS
CSinitiate(argc, argv, ccb)
i4                 *argc;
char               ***argv;
CS_CB              *ccb;

CSintr_ack - Acknowledge receipt of an interrupt

This routine turns off the CS_IRPENDING_MASK bit in the thread's state mask. This bit is set if a thread is informed of an interrupt when it is running. The next interruptible request will terminate with an interrupt after this happens, so this routine allows a thread to explicitly clear the flag when it knows about the interrupt.

See the section on Interrupts in the introduction for global interactions involving this routine, particularly the state table.

Inputs:

None

Outputs:

None

Returns:

None

Definition:

VOID
CSintr_ack()

CSi_semaphore - Initialize semaphore

CSi_semaphore is obsolete. It is replaced by CSw_semaphore.

This routine is used to initialize a semaphore for use by the CSp_semaphore and CSv_semaphore routines. This should always be called before the first use of a semaphore and needs only be called once. It should never be called on a semaphore that may be in use.

All calls to CSi_semaphore should be followed by a call to CSn_semaphore to give it a name.

Inputs:

sem A pointer to the semaphore to initialize
type
Semaphore type:
CS_SEM_SINGLE normal semaphore within a single server.
CS_SEM_MULTI semaphore is used to lock objects used concurrently by threads in multiple processes

Outputs:

None

Returns:

OK if operation succeeded, otherwise system specific error status.
E_CS0004_BAD_PARAMETER Illegal semaphore type specified.

Definition:

STATUS
CSi_semaphore(sem, type)
CS_SEMAPHORE		*sem;
i4			type;

CSmonitor - Implement the monitor task

This routine is called ala the regular thread processing routine. It parses its input, decides what to do, and returns the output.

(This is grossly under-specified, as most of the iimonitor command is implemented here. This will in time become obsolete as the much discussed monitoring architecture is rolled out.)

Inputs:

mode Mode of operation, CS_INPUT, _OUPUT, etc.
scb Sessions control block to monitor
command Text of the command
powerful Is this user powerful?
output_fcn Function to call to perform the output. This routine will be called as
(*output_fcn)(newline_present, length, buffer)
where buffer is the length character output string, and newline_present indicates whether a newline needs to be added to the end of the string.

Outputs:

next_mode mode of operation the thread should now observe, CS_INPUT, _OUPUT, etc.

Returns:

OK if operation succeeded, otherwise system specific error status.

Definition:

STATUS
CSmonitor(mode, scb, nmode, command, powerful, output_fcn)
i4                 mode;
CS_SB              *scb;
i4                 *next_mode;
char               *command;
i4                 powerful;
TR_FORMAT_FUNC	   *output_fcn;

CSms_thread_nap - put this thread to sleep for some millisecs

This routine puts the current thread to sleep for the indicated number of milliseconds. That is, this routine should return to its caller not immediately, but after (approximately) the indicated number of milliseconds have elapsed.

If the number of milliseconds is zero or negative, the routine will return immediately. This is probably not a useful feature, but at least it provides a definite specification of the behavior in such cases! Since time periods are not precisely controllable on many systems, all that a client of this routine can depend upon is that the routine will return no sooner than you asked, but you may be delayed indefinitely. A high-quality implementation will make every attempt to return after the specified interval, but no promises are possible.

During the time that the caller is asleep, other threads in this server should be allowed to run. A thread which is sleeping in CSms_thread_nap cannot be interrupted by a CSattn() call. If a CSattn() call is made against a thread which is currently in CSms_thread_nap(), the effect is just to set the "interrupt pending" flag for this session.

A thread which is sleeping in CSms_thread_nap cannot be awoken by a CSresume() call. If a CSresume() call is made against a thread which is currently in CSms_thread_nap, the effect is just to set the "event done" flag for this session.

Note that the time period passed to this routine is a "i4", meaning that a caller should not depend on being able to sleep longer than 32 seconds. Current implementations of this routine are optimized for very small intervals, however, since current usage passes values in the range 20 milliseconds to 100 milliseconds. If a caller wishes to use this routine to sleep for minutes or more, the caller must code a loop around this routine, repeatedly calling this routine to sleep for 32 seconds until the desired time period has elapsed.

Usage: This routine is used by the "Group Commit" feature of the server's logging system. The intent of this feature is to optimize log file throughput by packing log file pages as full as possible. This routine is called by a special server thread, called the Group Commit thread, which is monitoring the log file page, delaying the writing of the page for a short period in the hope that additional records will be added to the page.

The value of the 'ms' argument is controlled by a server startup parameter, and defaults to 20.

Inputs:

ms number of milliseconds to sleep.

Outputs:

None

Returns:

VOID

Definition:

VOID CSms_thread_nap( i4  ms );

CSn_semaphore - Attach a name to a CS_SEMAPHORE

CSi_semaphore is obsolete. It is replaced by CSw_semaphore.

Attach a (new) name to a CS_SEMAPHORE structure for debugging and monitoring purposes.

The maximum length of a name is CS_SEM_NAME_LEN (GL_MAXNAME) characters - names longer than this are silently truncated.

Names can be attached to CS_SEM_SINGLE or CS_SEM_MULTI semaphores. All semaphores should be named.

Inputs:

sem CS_SEMAPHORE to name
name String containing name. This will be copied into store visible to all users of the semaphore and so need not remain after this call

Outputs:

None

Returns:

OK

Side Effects:

This routine may register the name with some kind of monitoring service.

Prototype:

STATUS
CSn_semaphore(CS_SEMAPHORE *sem, char *name);

CSp_semaphore - perform a "P" operation on a semaphore

This routine is called to allow a thread to request a semaphore and if it is not available, to queue up for the semaphore. The thread requesting the semaphore will be returned to the ready queue when the semaphore is V'd.

At the time that the semaphore is granted, the fact that a semaphore is held by the thread is noted in the thread control block, to prevent the stopping of the thread (via the monitor) while a semaphore is held.

Shared semaphores may or may not be supported on a particular platform. 


If the requested semaphore has a type CS_SEM_MULTI then that semaphore may be located in shared memory and the granting/blocking on this semaphore must work between multiple processes. CS_SEM_MULTI semaphores are expected to model spin locks and should only be held for short periods of time. Clients should never do operations which may cause their thread to be suspended while holding a CS_SEM_MULTI semaphore.

All semaphores should be initialized with a CSw_semaphore call before being used by CSp_semaphore().

Inputs:

exclusive An obsolete flags parameter which indicated that the semaphore request was for exclusive ownership of the semaphore. It is now ignored \- all requests are exclusive.
sem

A pointer to a CS_SEMAPHORE for which the thread wishes to wait.

Outputs:

None

Returns:

OK if semaphore granted, otherwise system specific error status.
E_CS000F_REQUEST_ABORTED request interrupted.
E_CS0017_SMPR_DEADLOCK semaphore already held by requestor.

Definition:

STATUS
CSp_semaphore(exclusive, sem)
i4                 exclusive;
CS_SEMAPHORE       *sem;

CSr_semaphore - Remove a semaphore

This routine is used by a running thread to return any resources from a semaphore that is no longer needed. It must be called when a CS_SEMAPHORE which has been initialized with CSw_semaphore will no longer be needed, or will go out of context.

Inputs:

sem A pointer to the semaphore to be invalidated.

Outputs:

None

Returns:

OK
other system-specific errors.

Side Effects:

Calls to CSp_semaphore and CSv_semaphore may become invalid until CSw_semaphore is called again.

Definition:

STATUS
CSr_semaphore(sem)
CS_SEMAPHORE *sem;

CSremove - Cause a thread to be terminated

This routine is used to cause the dispatcher to remove a thread from competition for resources. It works by setting the next state for the thread to CS_TERMINATE and, from there, letting "nature take its course" in having each of the threads terminate themselves. This call is intended for use only by the monitor code.

Note that this routine does not evaporate a thread at any point other than when it has returned. The reason that this decision was made is to allow a thread to clean up after itself. Randomly evaporating threads will inevitably result in a trashed server because the thread which has been evaporated will have been holding some resource. The CS module, is cooperative; it cannot go clean up a thread's resources since it does not know what/where they are.

In order to force the thread to expeditiously enter its cleanup code, it may need to be interrupted by CSattn with an event type of CS_REMOVE_EVENT or CS_SHUTDOWN_EVENT. This should be done after calling CSremove.

Inputs:

sid The thread id to remove

Outputs:

None

Returns:

OK if operation succeeded, otherwise system specific error status.
E_CS0004_BAD_PARAMETER thread does not exist

Definition:

STATUS
CSremove( CS_SID sid );

CSresume - Mark thread as done with event

This routine is called to note that the session identified by the parameter has completed some event. It expects to run so that it cannot be interrupted, as it may have the world in an inconsistent state, but cannot use semaphores, since it may be being called by the o/s. In particular, on VMS it is a delivered AST.

CSresume is also the mechanism used by the client code to indicate that it wishes to have a new thread added. When a GClisten call completes successfully, the client code's GClisten completion handler calls CSresume with a special session id, defined as CS_ADDER_ID. CSresume should then arrange to add a new thread to the server. In current implementations, this is typically done by causing the server's admin thread to be resumed, and the admin thread will then add the new thread and start it running.

See the section on Interrupts in the introduction for global interactions involving this routine, particularly the state table.

Inputs:

sid Thread id for which event has completed. Certain sid's with special meaning may cause other operations to happen. For instance, a sid of CS_ADDER_ID will cause a new thread to be added.

Outputs:

None

Returns:

None

Side Effects:

The SCB for this thread is moved to the ready queue, if it is not already there (via an interrupt or timeout).
T