void sptrace_clear(PsmPartition trace) { PsmAddress traceHeaderAddress; TraceHeader *trh; PsmAddress elt; PsmAddress nextElt; PsmAddress itemAddress; TraceItem *item; if (!trace) return; traceHeaderAddress = psm_get_root(trace); trh = (TraceHeader *) psp(trace, traceHeaderAddress); CHKVOID(trh); for (elt = sm_list_first(trace, trh->log); elt; elt = nextElt) { nextElt = sm_list_next(trace, elt); itemAddress = sm_list_data(trace, elt); item = (TraceItem *) psp(trace, itemAddress); CHKVOID(item); if (item->opType == OP_ALLOCATE || item->opType == OP_FREE) { if (item->refOpNbr == 0) { continue; /* Not matched. */ } /* Delete matched activity from log. */ psm_free(trace, itemAddress); CHKVOID(sm_list_delete(trace, elt, NULL, NULL) == 0); } } }
PsmAddress sm_rbt_last(PsmPartition partition, PsmAddress rbt) { SmRbt *rbtPtr; PsmAddress node; PsmAddress last = 0; SmRbtNode *nodePtr; CHKZERO(partition); CHKZERO(rbt); rbtPtr = (SmRbt *) psp(partition, rbt); CHKZERO(rbtPtr); if (lockSmrbt(rbtPtr) == ERROR) { return 0; } node = rbtPtr->root; while (node) { last = node; nodePtr = (SmRbtNode *) psp(partition, node); if (nodePtr == NULL) { putErrmsg("Corrupt red-black tree.", NULL); last = 0; break; } node = nodePtr->child[RIGHT]; } unlockSmrbt(rbtPtr); return last; }
PsmAddress Sm_list_insert_after(const char *fileName, int lineNbr, PsmPartition partition, PsmAddress oldElt, PsmAddress data) { SmListElt *oldEltBuffer; PsmAddress list; SmList *listBuffer; CHKZERO(partition); CHKZERO(oldElt); oldEltBuffer = (SmListElt *) psp(partition, oldElt); CHKZERO(oldEltBuffer); if ((list = oldEltBuffer->list) == 0) { putErrmsg(_noListMsg(), NULL); return 0; } listBuffer = (SmList *) psp(partition, list); if (lockSmlist(listBuffer) == ERROR) { putErrmsg(_cannotLockMsg(), NULL); return 0; } return finishInsertingAfter(fileName, lineNbr, partition, oldElt, oldEltBuffer, list, listBuffer, data); }
PsmAddress Sm_rbt_traverse(PsmPartition partition, PsmAddress fromNode, int direction) { SmRbtNode *nodePtr; SmRbt *rbtPtr; int nextNode; CHKZERO(partition); CHKZERO(fromNode); nodePtr = (SmRbtNode *) psp(partition, fromNode); CHKZERO(nodePtr); rbtPtr = (SmRbt *) psp(partition, nodePtr->rbt); CHKZERO(rbtPtr); if (lockSmrbt(rbtPtr) == ERROR) { return 0; } if (direction != LEFT) { direction = RIGHT; } nextNode = traverseRbt(partition, fromNode, direction); unlockSmrbt(rbtPtr); return nextNode; }
static PsmAddress rotateOnce(PsmPartition partition, PsmAddress root, int direction) { int otherDirection = 1 - direction; SmRbtNode *rootPtr; PsmAddress pivot; SmRbtNode *pivotPtr; PsmAddress orphan; SmRbtNode *orphanPtr; rootPtr = (SmRbtNode *) psp(partition, root); pivot = rootPtr->child[otherDirection]; pivotPtr = (SmRbtNode *) psp(partition, pivot); orphan = pivotPtr->child[direction]; orphanPtr = (SmRbtNode *) psp(partition, orphan); pivotPtr->parent = rootPtr->parent; pivotPtr->child[direction] = root; pivotPtr->isRed = 0; rootPtr->parent = pivot; rootPtr->child[otherDirection] = orphan; rootPtr->isRed = 1; if (orphan) { orphanPtr->parent = root; } return pivot; }
static void applyRateControl(Sdr sdr) { BpVdb *vdb = getBpVdb(); PsmPartition ionwm = getIonwm(); Throttle *throttle; PsmAddress elt; VInduct *induct; VOutduct *outduct; long capacityLimit; sdr_begin_xn(sdr); /* Just to lock memory. */ /* Recalculate limit on local bundle generation. */ manageProductionThrottle(vdb); /* Enable some bundle acquisition. */ for (elt = sm_list_first(ionwm, vdb->inducts); elt; elt = sm_list_next(ionwm, elt)) { induct = (VInduct *) psp(ionwm, sm_list_data(ionwm, elt)); throttle = &(induct->acqThrottle); capacityLimit = throttle->nominalRate << 1; throttle->capacity += throttle->nominalRate; if (throttle->capacity > capacityLimit) { throttle->capacity = capacityLimit; } if (throttle->capacity > 0) { sm_SemGive(throttle->semaphore); } } /* Enable some bundle transmission. */ for (elt = sm_list_first(ionwm, vdb->outducts); elt; elt = sm_list_next(ionwm, elt)) { outduct = (VOutduct *) psp(ionwm, sm_list_data(ionwm, elt)); throttle = &(outduct->xmitThrottle); capacityLimit = throttle->nominalRate << 1; throttle->capacity += throttle->nominalRate; if (throttle->capacity > capacityLimit) { throttle->capacity = capacityLimit; } if (throttle->capacity > 0) { sm_SemGive(throttle->semaphore); } } sdr_exit_xn(sdr); /* Unlock memory. */ }
PsmAddress postProbeEvent(IonNode *node, Embargo *embargo) { PsmPartition ionwm = getIonwm(); PsmAddress addr; IonProbe *probe; IonVdb *ionvdb; IonNeighbor *neighbor; PsmAddress nextElt; unsigned int rtlt; /* Round-trip light time. */ int interval = 6; /* Minimum 6-sec interval. */ PsmAddress elt; IonProbe *pr; CHKZERO(node); CHKZERO(embargo); addr = psm_zalloc(ionwm, sizeof(IonProbe)); if (addr == 0) { putErrmsg("Can't create probe event.", NULL); return 0; } probe = (IonProbe *) psp(ionwm, addr); CHKZERO(probe); probe->time = getUTCTime(); probe->destNodeNbr = node->nodeNbr; probe->neighborNodeNbr = embargo->nodeNbr; /* Schedule next probe of this embargoed neighbor for the * time that is the current time plus 2x the round-trip * light time from the local node to the neighbor (but * at least 6 seconds). */ ionvdb = getIonVdb(); neighbor = findNeighbor(ionvdb, embargo->nodeNbr, &nextElt); if (neighbor) { rtlt = (neighbor->owltOutbound + neighbor->owltInbound) << 1; if (rtlt > interval) { interval = rtlt; } } probe->time += interval; for (elt = sm_list_last(ionwm, ionvdb->probes); elt; elt = sm_list_prev(ionwm, elt)) { pr = (IonProbe *) psp(ionwm, sm_list_data(ionwm, elt)); CHKZERO(pr); if (pr->time <= probe->time) { return sm_list_insert_after(ionwm, elt, addr); } } return sm_list_insert_first(ionwm, ionvdb->probes, addr); }
PsmAddress Sm_list_insert(const char *fileName, int lineNbr, PsmPartition partition, PsmAddress list, PsmAddress data, SmListCompareFn compare, void *argData) { SmList *listBuffer; PsmAddress elt; SmListElt *eltBuffer; if (compare == (SmListCompareFn) NULL) { /* List is assumed to be unsorted. We simply add the new element at the end of the list. */ return Sm_list_insert_last(fileName, lineNbr, partition, list, data); } /* Using user-specified comparison function. List is assumed to be in sorted order. */ CHKZERO(partition); CHKZERO(list); listBuffer = (SmList *) psp(partition, list); CHKZERO(listBuffer); if (lockSmlist(listBuffer) == ERROR) { putErrmsg(_cannotLockMsg(), NULL); return 0; } /* Find position to insert new data into list. Start from end of list to keep sort stable; sort sequence is implicitly FIFO within key, i.e., we insert element AFTER the last element in the table with the same key value. */ for (elt = listBuffer->last; elt != 0; elt = eltBuffer->prev) { eltBuffer = (SmListElt *) psp(partition, elt); CHKZERO(eltBuffer); if (compare(partition, eltBuffer->data, argData) <= 0) { break; } } /* insert into list */ if (elt == 0) { return finishInsertingFirst(fileName, lineNbr, partition, list, listBuffer, data); } return finishInsertingAfter(fileName, lineNbr, partition, elt, eltBuffer, list, listBuffer, data); }
PsmAddress Sm_list_insert_before(const char *fileName, int lineNbr, PsmPartition partition, PsmAddress oldElt, PsmAddress data) { SmListElt *oldEltBuffer; PsmAddress list; SmList *listBuffer; PsmAddress elt; SmListElt *eltBuffer; CHKZERO(partition); CHKZERO(oldElt); oldEltBuffer = (SmListElt *) psp(partition, oldElt); CHKZERO(oldEltBuffer); if ((list = oldEltBuffer->list) == 0) { putErrmsg(_noListMsg(), NULL); return 0; } listBuffer = (SmList *) psp(partition, list); if (lockSmlist(listBuffer) == ERROR) { putErrmsg(_cannotLockMsg(), NULL); return 0; } elt = Psm_zalloc(fileName, lineNbr, partition, sizeof(SmListElt)); if (elt == 0) { unlockSmlist(listBuffer); putErrmsg(_noSpaceForEltMsg(), NULL); return 0; } eltBuffer = (SmListElt *) psp(partition, elt); eraseListElt(eltBuffer); eltBuffer->list = list; eltBuffer->data = data; eltBuffer->prev = oldEltBuffer->prev; eltBuffer->next = oldElt; if (oldEltBuffer->prev != 0) { eltBuffer = (SmListElt *) psp(partition, oldEltBuffer->prev); CHKZERO(eltBuffer); eltBuffer->next = elt; } else { listBuffer->first = elt; } oldEltBuffer->prev = elt; listBuffer->length += 1; unlockSmlist(listBuffer); return elt; }
void sptrace_log_free(PsmPartition trace, unsigned long addr, char *fileName, int lineNbr) { PsmAddress elt; TraceItem *item; TraceItem *refitem; if (!trace) return; logEvent(trace, OP_FREE, addr, -1, NULL, fileName, lineNbr, &elt); if (elt) /* Event was logged. */ { item = (TraceItem *) psp(trace, sm_list_data(trace, elt)); /* Find matching allocation, close it out. */ elt = sm_list_prev(trace, elt); while (elt) { refitem = (TraceItem *) psp(trace, sm_list_data(trace, elt)); CHKVOID(refitem); if (refitem->objectAddress != item->objectAddress) { elt = sm_list_prev(trace, elt); continue; } /* Found match. */ switch (refitem->opType) { case OP_MEMO: /* Ignore it. */ elt = sm_list_prev(trace, elt); continue; case OP_FREE: /* Duplicate free. */ return; } /* Found most recent open allocation. */ item->refTaskId = refitem->taskId; item->refFileName = refitem->fileName; item->refLineNbr = refitem->lineNbr; item->refOpNbr = refitem->opNbr; item->objectSize = refitem->objectSize; refitem->refTaskId = item->taskId; refitem->refFileName = item->fileName; refitem->refLineNbr = item->lineNbr; refitem->refOpNbr = item->opNbr; return; } } }
int treeBroken(PsmPartition partition, PsmAddress rbt) { SmRbt *rbtPtr; rbtPtr = (SmRbt *) psp(partition, rbt); return (subtreeBlackHeight(partition, rbtPtr->root) == 0); }
bool DOS_FCBOpen(Bit16u seg,Bit16u offset) { DOS_FCB fcb(seg,offset); char shortname[DOS_FCBNAME];Bit16u handle; fcb.GetName(shortname); /* First check if the name is correct */ Bit8u drive; char fullname[DOS_PATHLENGTH]; if (!DOS_MakeName(shortname,fullname,&drive)) return false; /* Check, if file is already opened */ for (Bit8u i=0;i<DOS_FILES;i++) { DOS_PSP psp(dos.psp()); if (Files[i] && Files[i]->IsOpen() && Files[i]->IsName(fullname)) { handle = psp.FindEntryByHandle(i); if (handle==0xFF) { // This shouldnt happen LOG(LOG_FILES,LOG_ERROR)("DOS: File %s is opened but has no psp entry.",shortname); return false; } fcb.FileOpen((Bit8u)handle); return true; } } if (!DOS_OpenFile(shortname,OPEN_READWRITE,&handle)) return false; fcb.FileOpen((Bit8u)handle); return true; }
bool DOS_DuplicateEntry(Bit16u entry,Bit16u * newentry) { // Dont duplicate console handles /* if (entry<=STDPRN) { *newentry = entry; return true; }; */ Bit8u handle=RealHandle(entry); if (handle>=DOS_FILES) { DOS_SetError(DOSERR_INVALID_HANDLE); return false; }; if (!Files[handle] || !Files[handle]->IsOpen()) { DOS_SetError(DOSERR_INVALID_HANDLE); return false; }; DOS_PSP psp(dos.psp()); *newentry = psp.FindFreeFileEntry(); if (*newentry==0xff) { DOS_SetError(DOSERR_TOO_MANY_OPEN_FILES); return false; } Files[handle]->AddRef(); psp.SetFileHandle(*newentry,handle); return true; }
void removeEmbargo(IonNode *node, uvast neighborNodeNbr) { PsmPartition ionwm = getIonwm(); PsmAddress elt; PsmAddress addr; Embargo *embargo; CHKVOID(node); for (elt = sm_list_first(ionwm, node->embargoes); elt; elt = sm_list_next(ionwm, elt)) { addr = sm_list_data(ionwm, elt); embargo = (Embargo *) psp(ionwm, addr); CHKVOID(embargo); if (embargo->nodeNbr < neighborNodeNbr) { continue; } if (embargo->nodeNbr > neighborNodeNbr) { return; /* Embargo not found. */ } break; /* Found the embargo to remove. */ } if (elt == 0) { return; /* Embargo not found. */ } oK(sm_list_delete(ionwm, elt, NULL, NULL)); psm_free(ionwm, addr); }
PsmAddress Sm_list_create(const char *fileName, int lineNbr, PsmPartition partition) { sm_SemId lock; PsmAddress list; SmList *listBuffer; lock = sm_SemCreate(SM_NO_KEY, SM_SEM_FIFO); if (lock < 0) { putErrmsg("Can't create semaphore for list.", NULL); return 0; } list = Psm_zalloc(fileName, lineNbr, partition, sizeof(SmList)); if (list == 0) { sm_SemDelete(lock); putErrmsg("Can't allocate space for list header.", NULL); return 0; } listBuffer = (SmList *) psp(partition, list); eraseList(listBuffer); listBuffer->lock = lock; return list; }
PsmAddress Sm_rbt_create(char *file, int line, PsmPartition partition) { sm_SemId lock; PsmAddress rbt; SmRbt *rbtPtr; lock = sm_SemCreate(SM_NO_KEY, SM_SEM_FIFO); if (lock < 0) { putErrmsg("Can't create semaphore for rbt.", NULL); return 0; } rbt = Psm_zalloc(file, line, partition, sizeof(SmRbt)); if (rbt == 0) { sm_SemDelete(lock); putErrmsg("Can't allocate space for rbt object.", NULL); return 0; } rbtPtr = (SmRbt *) psp(partition, rbt); eraseTree(rbtPtr); rbtPtr->lock = lock; return rbt; }
IonNode *addNode(IonVdb *ionvdb, uvast nodeNbr) { PsmPartition ionwm = getIonwm(); PsmAddress addr; PsmAddress elt; IonNode *node; addr = psm_zalloc(ionwm, sizeof(IonNode)); if (addr == 0) { putErrmsg("Can't add node.", NULL); return NULL; } node = (IonNode *) psp(ionwm, addr); CHKNULL(node); memset((char *) node, 0, sizeof(IonNode)); node->nodeNbr = nodeNbr; elt = sm_rbt_insert(ionwm, ionvdb->nodes, addr, rfx_order_nodes, node); if (elt == 0) { psm_free(ionwm, addr); putErrmsg("Can't add node.", NULL); return NULL; } node->embargoes = sm_list_create(ionwm); return node; }
static PsmAddress createNode(char *file, int line, PsmPartition partition, PsmAddress rbt, PsmAddress parent, PsmAddress data, SmRbtNode **buffer) { PsmAddress node; SmRbtNode *nodePtr; node = Psm_zalloc(file, line, partition, sizeof(SmRbtNode)); if (node == 0) { putErrmsg("Can't allocate space for rbt node.", NULL); return 0; } nodePtr = (SmRbtNode *) psp(partition, node); nodePtr->rbt = rbt; nodePtr->parent = parent; nodePtr->child[LEFT] = 0; nodePtr->child[RIGHT] = 0; nodePtr->data = data; if (buffer) /* Tree already has a root. */ { nodePtr->isRed = 1; *buffer = nodePtr; } else /* This is the first node in the tree. */ { nodePtr->isRed = 0; /* Root is always black. */ } return node; }
static void dropVdb(PsmPartition wm, PsmAddress vdbAddress) { IonVdb *vdb; vdb = (IonVdb *) psp(wm, vdbAddress); /* Time-ordered list of probes can simply be destroyed. */ sm_list_destroy(wm, vdb->probes, rfx_erase_data, NULL); /* Three of the red-black tables in the Vdb are * emptied and recreated by rfx_stop(). Destroy them. */ sm_rbt_destroy(wm, vdb->contactIndex, NULL, NULL); sm_rbt_destroy(wm, vdb->rangeIndex, NULL, NULL); sm_rbt_destroy(wm, vdb->timeline, NULL, NULL); /* cgr_stop clears all routing objects, so nodes and * neighbors themselves can now be deleted. */ sm_rbt_destroy(wm, vdb->nodes, destroyIonNode, NULL); sm_rbt_destroy(wm, vdb->neighbors, rfx_erase_data, NULL); /* Safely delete the ZCO availability semaphore. */ sm_SemEnd(vdb->zcoSemaphore); sm_SemDelete(vdb->zcoSemaphore); vdb->zcoSemaphore = SM_SEM_NONE; vdb->zcoClaimants = 0; vdb->zcoClaims = 0; zco_unregister_callback(); }
bool DOS_FCBRenameFile(Bit16u seg, Bit16u offset) { DOS_FCB fcbold(seg,offset); DOS_FCB fcbnew(seg,offset+16); if(!fcbold.Valid()) return false; char oldname[DOS_FCBNAME]; char newname[DOS_FCBNAME]; fcbold.GetName(oldname); fcbnew.GetName(newname); /* Check, if sourcefile is still open. This was possible in DOS, but modern oses don't like this */ Bit8u drive; char fullname[DOS_PATHLENGTH]; if (!DOS_MakeName(oldname,fullname,&drive)) return false; DOS_PSP psp(dos.psp()); for (Bit8u i=0; i<DOS_FILES; i++) { if (Files[i] && Files[i]->IsOpen() && Files[i]->IsName(fullname)) { Bit16u handle = psp.FindEntryByHandle(i); //(more than once maybe) if (handle == 0xFF) { DOS_CloseFile(i,true); } else { DOS_CloseFile(handle); } } } /* Rename the file */ return DOS_Rename(oldname,newname); }
static void infoProfile(int tokenCount, char **tokens) { DtpcVdb *vdb = getDtpcVdb(); Profile *vprofile; PsmAddress elt; PsmPartition wm = getIonwm(); unsigned int profileID; if (tokenCount != 3) { SYNTAX_ERROR; return; } profileID = atoi(tokens[2]); for (elt = sm_list_first(wm, vdb->profiles); elt; elt = sm_list_next(wm, elt)) { vprofile = (Profile *) psp(wm, sm_list_data(wm, elt)); if (vprofile->profileID == profileID) { break; } } if (elt == 0) { printText("Unknown profile."); return; } printProfile(vprofile); }
static void destroyIonNode(PsmPartition partition, PsmAddress eltData, void *argument) { IonNode *node = (IonNode *) psp(partition, eltData); sm_list_destroy(partition, node->embargoes, rfx_erase_data, NULL); psm_free(partition, eltData); }
static void dropVdb(PsmPartition wm, PsmAddress vdbAddress) { IonVdb *vdb; int i; PsmAddress elt; PsmAddress nextElt; PsmAddress addr; Requisition *req; vdb = (IonVdb *) psp(wm, vdbAddress); /* Time-ordered list of probes can simply be destroyed. */ sm_list_destroy(wm, vdb->probes, rfx_erase_data, NULL); /* Three of the red-black tables in the Vdb are * emptied and recreated by rfx_stop(). Destroy them. */ sm_rbt_destroy(wm, vdb->contactIndex, NULL, NULL); sm_rbt_destroy(wm, vdb->rangeIndex, NULL, NULL); sm_rbt_destroy(wm, vdb->timeline, NULL, NULL); /* cgr_stop clears all routing objects, so nodes and * neighbors themselves can now be deleted. */ sm_rbt_destroy(wm, vdb->nodes, destroyIonNode, NULL); sm_rbt_destroy(wm, vdb->neighbors, rfx_erase_data, NULL); /* Safely shut down the ZCO flow control system. */ for (i = 0; i < 1; i++) { for (elt = sm_list_first(wm, vdb->requisitions[i]); elt; elt = nextElt) { nextElt = sm_list_next(wm, elt); addr = sm_list_data(wm, elt); req = (Requisition *) psp(wm, addr); sm_SemEnd(req->semaphore); psm_free(wm, addr); sm_list_delete(wm, elt, NULL, NULL); } } //zco_unregister_callback(); }
static int wipeList(const char *fileName, int lineNbr, PsmPartition partition, PsmAddress list, SmListDeleteFn deleteFn, void *arg, int destroy) { SmList *listBuffer; PsmAddress elt; PsmAddress next; SmListElt *eltBuffer; listBuffer = (SmList *) psp(partition, list); if (lockSmlist(listBuffer) < 0) { putErrmsg(_cannotLockMsg(), NULL); return -1; } for (elt = listBuffer->first; elt != 0; elt = next) { eltBuffer = (SmListElt *) psp(partition, elt); CHKERR(eltBuffer); next = eltBuffer->next; if (deleteFn) { deleteFn(partition, elt, arg); } /* clear in case user mistakenly accesses later... */ eraseListElt(eltBuffer); Psm_free(fileName, lineNbr, partition, elt); } eraseList(listBuffer); if (destroy) { sm_SemDelete(listBuffer->lock); listBuffer->lock = SM_SEM_NONE; Psm_free(fileName, lineNbr, partition, list); } else { unlockSmlist(listBuffer); } return 0; }
bool DOS_ChildPSP(Bit16u segment, Bit16u size) { DOS_PSP psp(segment); psp.MakeNew(size); DOS_PSP psp_parent(psp.GetParent()); psp.CopyFileTable(&psp_parent,true); psp.SetEnvironment(psp_parent.GetEnvironment()); psp.SetSize(size); return true; };
void sm_list_unwedge(PsmPartition partition, PsmAddress list, int interval) { SmList *listBuffer; CHKVOID(partition); listBuffer = (SmList *) psp(partition, list); CHKVOID(listBuffer); sm_SemUnwedge(listBuffer->lock, interval); }
PsmPartition sptrace_join(int smkey, int smsize, char *sm, PsmPartition trace, char *name) { int nameLen; int smid; PsmMgtOutcome outcome; TraceHeader *trh; CHKNULL(trace); CHKNULL(smsize > 0); CHKNULL(name); if ((nameLen = strlen(name)) < 1 || nameLen > 31) { sptracePrint("start: name must be 1-31 characters."); return NULL; } /* Attach to shared memory used for trace operations. */ if (sm_ShmAttach(smkey, smsize, (char **) &sm, &smid) < 0) { sptracePrint("join: can't attach shared memory for trace."); return NULL; } /* Examine the shared memory region. */ if (psm_manage(sm, smsize, name, &trace, &outcome) < 0) { sptracePrint("join: shared memory mgt failed."); return NULL; } switch (outcome) { case Refused: sptracePrint("join: can't psm_manage shared memory."); return NULL; case Redundant: trh = (TraceHeader *) psp(trace, psm_get_root(trace)); if (trh == NULL || strcmp(name, trh->name) != 0) { sptracePrint("join: shared memory used otherwise."); return NULL; } return trace; /* Have joined the trace. */ default: break; } sptracePrint("join: trace episode not yet started."); return NULL; }
bool DOS_NewPSP(Bit16u segment, Bit16u size) { DOS_PSP psp(segment); psp.MakeNew(size); Bit16u parent_psp_seg=psp.GetParent(); DOS_PSP psp_parent(parent_psp_seg); psp.CopyFileTable(&psp_parent,false); // copy command line as well (Kings Quest AGI -cga switch) psp.SetCommandTail(RealMake(parent_psp_seg,0x80)); return true; };
PsmAddress sm_rbt_data(PsmPartition partition, PsmAddress node) { SmRbtNode *nodePtr; CHKZERO(partition); CHKZERO(node); nodePtr = (SmRbtNode *) psp(partition, node); CHKZERO(nodePtr); return nodePtr->data; }
void sm_rbt_unwedge(PsmPartition partition, PsmAddress rbt, int interval) { SmRbt *rbtPtr; CHKVOID(partition); CHKVOID(rbt); rbtPtr = (SmRbt *) psp(partition, rbt); CHKVOID(rbtPtr); sm_SemUnwedge(rbtPtr->lock, interval); }