一个嵌入式系统的C代码

源代码在线查看: ipc.cpp

软件大小: 435 K
上传用户: pipinooad
关键词: 嵌入式系统 C代码
下载地址: 免注册下载 普通下载 VIP

相关代码

				//*************************************************************************				//  MODULE : IPC - Inter Process Communication module			  *				//  AUTHOR : Ron Chernich                                                 *				//  PURPOSE: This module contains the Kernel IPC functions and the	  *				//	     supporting object methods, such as semaphores.		  *				//  HISTORY:                                                              *				//    08-MAR-94 Split off from Exec module				  *				//    13-APR-94 Semaphore count initialisation added			  *				//    19-APR-94 SemDelUser must NULL pst to prevent bad deletes by ::dtor *				//*************************************************************************								#include "exec.hpp"	    // related header				#include "kernel.hpp"	    // can't put this in header due recursion												///////////////////////////////////////////////////////////////////////////				//		   Class Methods for Semaphores				//-------------------------------------------------------------------------				// Constructor must Init the queues and null the name .. destructor will				// cleanup any memory in use (in case of a dis-orderly shut-down)				//				Sem4::Sem4 (void) : uPid(FALSE), uDelayed(TRUE), pst(NULL), uCount(0)  { }								Sem4::~Sem4 (void)				{				  if (pst)				   DELETE_ARRAY pst;				}								///////////				// Open the semaphore for use and set its count and (optional) name string.				// The passed PID is added to the user stack and saved as the "creator".				//				void Sem4::SemOpen (PCB &proc, UINT16 uCnt, char *pszName)				{				  if (this->SemIsFree()) {				    uCount = uCnt;				    uCreator = proc.uPid;				    if (pszName && strlen(pszName))				      if (pst = new char[strlen(pszName)+1])				        strcpy(pst, pszName);				    this->SemAddUser(proc);				  }				}				        				////////////////				// Allows us to use the "==" operator on a semaphore reference to test its				// name string.				// RETURNS: TRUE  .. it's a match				//          FALSE .. different				//				BOOL Sem4::operator == (char *pszName)				{				  if (pst && (strcmp(pst, pszName) == 0))				    return TRUE;				  return FALSE;				}								////////				// The semaphore is no longer in use when the PID queue is empty				// RETURNS: TRUE  .. yes it is				//	    FALSE .. no it ain't				//				BOOL Sem4::SemIsFree (void)				{				  return uPid.PqEmpty();				}								///////				// Check if the passed PID is using the semaphore				// RETURNS: TRUE  .. yes it is				//	    FALSE .. no it ain't				//				BOOL Sem4::SemIsUser (PCB &proc)				{				  return uPid.PqFind(proc.uPid);				}								///////				// Adds the passed process to the list of users of this semaphore				// RETURNS: TRUE  .. User added				//	    FALSE .. user was already a user!				//				BOOL Sem4::SemAddUser (PCB &proc)				{				  if (!uPid.PqFind(proc.uPid)) {				    uPid.PqAdd(proc);				    return TRUE;				  }				  return FALSE;				}								/////////////				// Remove passed PID from stack of registered users and the queue of				// delayed processes (if it's there).  If the stack becomes empty,				// the semaphore is "free" and its name (if any) is removed.				// RETURNS: TRUE  .. User removed				//	    FALSE .. user was not a user!				//				BOOL Sem4::SemDelUser (PCB &proc)				{				  UINT16 uTemp = uPid.PqGet(proc.uPid);				  if (uTemp == proc.uPid)  {				    if (uDelayed.PqFind(proc.uPid))				      uDelayed.PqGet(proc.uPid);				    if (uPid.PqEmpty() && pst) {				      DELETE_ARRAY pst;				      pst = NULL;				    }				    return TRUE;				  }				  return FALSE;				}								///////////				// The passed PID wants to gain access to the semaphore.  Provided the				// current count is > zero, just decrement the count and return TRUE.  If				// the semaphore is fully in use, add the user PID# to the priority queue				// and indicate this to the caller by returning FALSE.				// RETURNS: TRUE  .. PID has exclusive use of resource				//          FALSE .. PID added to waiting PID queue				//				BOOL Sem4::SemWait (PCB &proc)				{				  if (uCount) {				    --uCount;				    return TRUE;				  }				  uDelayed.PqAdd(proc);				  return FALSE;				}								//////////				// Release a lock on the semaphore, incrementing the semaphore counter.				// RETURNS: TRUE  .. there are processes waiting for a lock				//          FALSE .. semaphore is temporarily "free"				//				BOOL Sem4::SemSignal (void)				{				  ++uCount;				  return (uDelayed.PqEmpty() ? FALSE : TRUE);  				}								/////////////				// Removes and returns the PID# at the head of the "delayed" queue.				// RETURNS: PID#, or NO_PROC if queue empty.				//				UINT16 Sem4::SemGetDelayed (void)				{				  return uDelayed.PqGet();				}												/////////////				// Removes and returns the PID# from the "delayed" queue.				// RETURNS: PID#, or NO_PROC if queue empty.				//				UINT16 Sem4::SemGetDelayed (UINT16 uPid)				{				  return uDelayed.PqGet(uPid);				}												///////////////////////////////////////////////////////////////////////////				//		   Exec Class Methods for IPC operations				//-------------------------------------------------------------------------				// Search the list of semaphores in use to see if any has the user				// supplied name as passed.  If found, add the current process to its				// list of users.				// RETURNS: Zero for "not found" or semaphore ID.				//				UINT16 Exec::IpcOpen (char *pszName)				{				  for (UINT16 idx = 0; idx < MAX_SEM; idx++)				    if (!arrSem[idx].SemIsFree() && (arrSem[idx] == pszName)) {				      arrSem[idx].SemAddUser(arrPCB[uCurProc]);				      UINT16 uSid = 0x01 				      arrPCB[uCurProc].uSemOpen |= uSid;				      return uSid;				    }				  return 0;				}								///////////				// Walk the semaphore array to locate the "lowest" unused one and allocate				// it to the currently active process.  The passed value is used to set the				// count (unity implies a binary semaphore). If the passed string pointer is				// non-null, "name" the semaphore with it.				// RETURNS: Semaphore ID, or				//          Zero if none are free or supplied name not unique				//				UINT16 Exec::IpcAlloc (char *pszName, UINT16 nInit)				{				  for (UINT16 idx = 0; idx < MAX_SEM; idx++)				    if (arrSem[idx].SemIsFree()) {				      arrSem[idx].SemOpen(arrPCB[uCurProc], nInit, pszName);				      UINT16 uSid = 0x01 				      arrPCB[uCurProc].uSemOpen |= uSid;				      return uSid;				    }				  return 0;  				}								/////////////				// The passed process wishes to close/free/release the semaphore with				// the passed ID. We can't assume that the process is the current one				// because this call could be as a result of an operator DElete action.				//				// As a result, another process may be able to acquire the semaphore.				// If so, unblock it and remove it from all other queues it may also				// have been patiently waiting in.				//				void Exec::IpcClose (UINT16 uPid, UINT16 uSid)				{				  if (arrPCB[uPid].uSemOpen & uSid) {				    UINT16 uBit = uSid;				    UINT16 idx;				    for ( idx = 0; !(uBit & 0x01); ++idx)				      uBit >>= 0x01;				    arrSem[idx].SemDelUser(arrPCB[uPid]);				    arrPCB[uPid].uSemOpen &= ~uSid;				    arrPCB[uPid].uSemWait &= ~uSid;				    if (arrPCB[uPid].uSemSet & uSid) {				      arrPCB[uPid].uSemSet &= ~uSid;				      UINT16 uHead = arrSem[uSid].SemGetDelayed();				      if (uHead != NO_PROC) {				        arrSem[idx].SemWait(arrPCB[uHead]);				        arrPCB[uHead].uSemSet |= uHead;				        arrPCB[uHead].uSemWait = 0;				        MSG msg(ID_Kernel, KM_Signal, uSid);				        PostReply(uPid, &msg);				      }				    }				  }				}								///////////////				// The passed PID has SIGNALED that is has completed the mutual exclusion				// action associated with the passed semaphore.  If the "delayed" priority				// queue is empty, we simply continue - otherwise we remove the process				// at the head of the queue for this semaphore and re-issue the 				// call for it - causing it to unblock and clean itself up for execution.				//				void Exec::IpcSignal (UINT16 uPid, UINT16 uSid)				{				  if (arrPCB[uPid].uSemOpen & uSid) {				    UINT16 uBit = uSid;				    UINT16 idx;				    for (idx = 0; !(uBit & 0x01); ++idx)				      uBit >>= 0x01;				    arrPCB[uPid].uSemSet &= ~uSid;				    if (arrSem[idx].SemSignal())				      IpcWait(arrSem[idx].SemGetDelayed(), uSid);				  }				}								///////////				// This function allows multiple wait requests by logical disjunction of				// semaphore ID numbers (powers of 2).  We must validate that all requests				// are for resources the process actually has open (returning -1 if ANY are				// invalid). There are then three cases to consider:				//				// 1. The semaphore(s) is NOT available. This should only arise when the				//    process is running. For each bit set in , place the PID				//    on the waiting queue, setting the corresponding PID bit-map. Finally,				//    block the process and return (0).				//    				// 2. A semaphore is available and the process has not "delayed" on it:				//    Add the PID to the semaphores "user" list, decrementing its count.				//    Flag the PID to show it has set this semaphore and return the ID of				//    the semaphore the process now has possession of (perhaps non-exclusive)				//				// 3. The process is currently blocked and a semaphore is now available:				//    This should only arise via a call from , having determined				//    that the delayed process is next in line for the passed specific				//    semaphore.  will have removed the PID from the "delayed"				//    queue, so add it to the "user" list, set the "set by me" PID bit-map				//    bit, then check the "I've been waiting on" bit-map.  If this semaphores				//    ID was NOT the only one, we must remove the PID from the "delayed"				//    queues of all the others. Then we need to cause the process to unblock				//    by creating a message structure which can be attached to the PID as the				//    reply. Finally, we can clear the "waiting on" bit-map and return the				//    ID the process now has posession of.				//				// RETURNS: Negative .. -1 indicates process has not opened the semaphore!				//          Positive .. Id of semaphore process now has possesion of.				//              Zero .. semaphore in use, process now blocked.				//				INT16 Exec::IpcWait (UINT16 uPid, UINT16 uSidMask)				{				  UINT32 uVal = 1;				  while (uVal < (UINT32)arrPCB[uPid].uSemOpen) {				    if ((UINT16)(uVal & 0xffff) & uSidMask)				      if (!(arrPCB[uPid].uSemOpen & (UINT16)uVal))				        return -1;				    uVal 				  }				  //				  // All requests valid, process previously blocked process first				  //				  if (arrPCB[uPid].uSemWait) {				    UINT16 idx = 0;				    UINT16 uBit = 1;				    while (arrPCB[uPid].uSemWait) {				      if (uBit == uSidMask)				        arrSem[idx].SemWait(arrPCB[uPid]);				      if (arrPCB[uPid].uSemWait & uBit)				        arrSem[idx].SemGetDelayed(uPid);				      arrPCB[uPid].uSemWait &= ~uBit;				      uBit 				      ++idx;  				    }				    arrPCB[uPid].uSemSet |= uSidMask;				    MSG msg(ID_Kernel, KM_Signal, uSidMask);				    PostReply(uPid, &msg);				    return uSidMask;				  }				  //				  // process all possession requests until one is granted, or all block				  // If one is granted, unwind any that blocked.				  //				  if ((uPid == uCurProc) && (arrPCB[uPid].uSemWait == 0)) {				    UINT16 idx = 0;				    UINT16 uBit = 1;				    UINT16 uBitCpy = uSidMask;				    while (uBitCpy) {				      if ((uBitCpy & uBit) && arrSem[idx].SemGetCount()) {				        arrSem[idx].SemWait(arrPCB[uPid]);				        arrPCB[uPid].uSemSet |= uBit;				        return uBit;				      }				      uBitCpy &= ~uBit;				      uBit 				      ++idx;				    }				    idx = 0;				    uBit = 1;				    uBitCpy = uSidMask;				    while (uBitCpy) {				      if (uBitCpy & uBit) {				        arrSem[idx].SemWait(arrPCB[uPid]);				        arrPCB[uPid].uSemWait |= uBit;				      }				      uBitCpy &= ~uBit;				      uBit 				      ++idx;				    }				    Block();				  }				  return 0;				}								/////////////////////////////////// eof ////////////////////////////////////											

相关资源