doors.c
来自「Sun公司Dream项目」· C语言 代码 · 共 679 行 · 第 1/2 页
C
679 行
LOG_DBG(('r', "doorsNew(0x%llx, 0x%x)", doors->id, thr_self()));
#if DOORS_BUG
CHECK_IF_ERRNO(mutex_lock(&doors->lock));
doors->isInitialized = TRUE;
CHECK_IF_ERRNO(cond_broadcast(&doors->initializedCond));
CHECK_IF_ERRNO(mutex_unlock(&doors->lock));
#endif /* DOORS_BUG */
return doors;
}
Doors
doorsNewWithFile(Object delegate, DoorsThreadInitFunc threadInitFunc,
DoorsServerFunc serverFunc, DoorsNoClientFunc noClientFunc,
size_t stackSize, int maxThreadCount, const char *file, uid_t uid,
gid_t gid, mode_t mode)
{
Doors doors = doorsNew(delegate, threadInitFunc, serverFunc, noClientFunc,
stackSize, maxThreadCount);
int fd;
(void) unlink(file);
if ((fd = open(file, O_RDWR | O_CREAT | O_NOCTTY, mode)) < 0) {
logLibErrno(cobjs_TEXT_DOMAIN, "FATAL: open(%s)", file);
abort();
}
ABORT_ON_ERRNO(fchmod(fd, mode));
ABORT_ON_ERRNO(fchown(fd, uid, gid));
(void) close(fd);
if (fattach(doors->fd, file) < 0) {
logLibErrno(cobjs_TEXT_DOMAIN, "FATAL: fattach(%s)", file);
abort();
}
doors->file = strdup(file);
return doors;
}
/*************************************************************************
* Instance Methods
*************************************************************************/
void *
doorsResultBuffer(size_t size, size_t count)
{
DoorBuffer *dbp;
ABORT_IF_ERRNO(thr_getspecific(resultBufferKey, (void **)&dbp));
if (dbp == NULL) {
dbp = NEW_ZEROED(DoorBuffer, 1);
ABORT_IF_ERRNO(thr_setspecific(resultBufferKey, dbp));
}
if (dbp->size < count * size) {
dbp->body = REALLOC(dbp->body, count, size);
dbp->size = count * size;
}
return dbp->body;
}
door_desc_t *
doorsDescBuffer(size_t count)
{
DoorBuffer *dbp;
ABORT_IF_ERRNO(thr_getspecific(descBufferKey, (void **)&dbp));
if (dbp == NULL) {
dbp = NEW_ZEROED(DoorBuffer, 1);
ABORT_IF_ERRNO(thr_setspecific(descBufferKey, dbp));
}
if (dbp->size < count * sizeof(door_desc_t)) {
dbp->body = REALLOC(dbp->body, count, sizeof(door_desc_t));
dbp->size = count * sizeof(door_desc_t);
}
return (door_desc_t *)dbp->body;
}
void
doorsNoClient(Doors doors)
{
DoorsParameters p;
Boolean doShutdown = FALSE;
LOG_DBG(('r', "doorsNoClient(0x%llx, 0x%x)", doors->id,
thr_self()));
CHECK_IF_ERRNO(mutex_lock(&doors->lock));
if (! doors->doingNoClient) {
doors->doingNoClient = TRUE;
doShutdown = TRUE;
}
CHECK_IF_ERRNO(mutex_unlock(&doors->lock));
if (doShutdown) {
LOG_DBG(('r', "doorsNoClient(0x%llx, 0x%x) shutdown", doors->id,
thr_self()));
p.command = DOORS_COMMAND_NO_CLIENT;
p.doors = doors;
actionInitiate(noClientAction, commandActor, &p,
ACTION_TYPE_NO_RESULTS);
}
}
void
doorsSetTrace(Doors doors, Boolean doTrace)
{
CHECK_IF_ERRNO(mutex_lock(&doors->lock));
doors->doTrace = doTrace;
CHECK_IF_ERRNO(mutex_unlock(&doors->lock));
}
void
doorsFree(Doors doors)
{
if (doors->file != NULL) {
ABORT_ON_ERRNO(fdetach(doors->file));
free(doors->file);
}
/*
* Terminate threads in private pool
*/
CHECK_IF_ERRNO(mutex_lock(&doors->lock));
LOG_DBG(('r', "doorsFree(0x%llx, 0x%x) called, count %d", doors->id,
thr_self(), doors->threadCount));
ASSERT(! doors->doingShutdown);
doors->doingShutdown = TRUE;
#if DOORS_BUG2
doors->isPendingWait = TRUE;
while (doors->pendingCreates > 0) {
LOG_DBG(('r', "doorsFree(0x%llx, 0x%x) pending wait, pending %d",
doors->id, thr_self(), doors->pendingCreates));
CHECK_IF_ERRNO(cond_wait(&doors->pendingCond, &doors->lock));
}
#endif /* DOORS_BUG2 */
while (doors->threadCount > 0) {
LOG_DBG(('r', "doorsFree(0x%llx, 0x%x), doorCall start count %d",
doors->id, thr_self(), doors->threadCount));
CHECK_IF_ERRNO(mutex_unlock(&doors->lock));
/*
* Do door_calls on all threads, doorsServerFunc sees shutdown TRUE
* and if the door_call() was from this pid, does a thr_exit().
*/
(void)door_call(doors->fd, NULL);
CHECK_IF_ERRNO(mutex_lock(&doors->lock));
LOG_DBG(('r', "doorsFree(0x%llx, 0x%x), doorCall done count %d",
doors->id, thr_self(), doors->threadCount));
}
LOG_DBG(('r', "doorsFree(0x%llx, 0x%x), door revoke", doors->id,
thr_self()));
CHECK_IF_ERRNO(mutex_unlock(&doors->lock));
ABORT_ON_ERRNO(door_revoke(doors->fd));
LOG_DBG(('r', "doorsFree(0x%llx, 0x%x), door revoke done", doors->id,
thr_self()));
#if DOORS_BUG
CHECK_IF_ERRNO(cond_destroy(&doors->initializedCond));
#endif /* DOORS_BUG */
#if DOORS_BUG2
CHECK_IF_ERRNO(cond_destroy(&doors->pendingCond));
#endif /* DOORS_BUG2 */
CHECK_IF_ERRNO(mutex_destroy(&doors->lock));
free(doors);
}
/*************************************************************************
* Private Methods
*************************************************************************/
/*
* Non-inlinable called from inline
*
* INLINE_PRIVATE void
* doorsInlinePrivate(void)
* {
* }
*/
static void *
doorsThreadInit(void *arg)
{
Doors doors = (Doors) arg;
#if DOORS_BUG
CHECK_IF_ERRNO(mutex_lock(&doors->lock));
while (! doors->isInitialized) {
CHECK_IF_ERRNO(cond_wait(&doors->initializedCond, &doors->lock));
}
CHECK_IF_ERRNO(mutex_unlock(&doors->lock));
#endif /* DOORS_BUG */
LOG_DBG(('r', "doorsThreadInit(0x%llx, 0x%x)", doors->id, thr_self()));
if (doors->threadInitFunc != NULL) {
(*doors->threadInitFunc)(doors->delegate);
}
LOG_DBG(('r', "doorsThreadInit(0x%llx, 0x%x) door_bind", doors->id,
thr_self()));
ABORT_ON_ERRNO(door_bind(doors->fd));
LOG_DBG(('r', "doorsThreadInit(0x%llx, 0x%x) door_bind done", doors->id,
thr_self()));
ABORT_IF_ERRNO(pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL));
LOG_DBG(('r', "doorsThreadInit(0x%llx, 0x%x) door_return", doors->id,
thr_self()));
#if DOORS_BUG2
CHECK_IF_ERRNO(mutex_lock(&doors->lock));
ASSERT(doors->pendingCreates > 0);
if (--doors->pendingCreates == 0 && doors->isPendingWait) {
CHECK_IF_ERRNO(cond_broadcast(&doors->pendingCond));
}
CHECK_IF_ERRNO(mutex_unlock(&doors->lock));
#endif /* DOORS_BUG2 */
ABORT_ON_ERRNO(door_return(NULL, 0, NULL, 0));
return NULL; /* for lint */
}
static void
doorsServerFunc(void *cookie, /*const void*/ char *argp, size_t argSize,
/*const*/ door_desc_t *descp, size_t nDesc)
{
Doors doors = (Doors) cookie;
DoorsResultData retData;
if (argp == DOOR_UNREF_DATA) {
ASSERT(doors->noClientFunc != NULL);
LOG_DBG(('r', "doorsServerFunc(0x%llx, 0x%x) UNREF DOOR",
doors->id, thr_self()));
doorsNoClient(doors);
retData = nullRetData;
} else {
door_cred_t cred;
if (door_cred(&cred) != 0) {
LOG_DBG(('r', "doorsServerFunc(0x%llx, 0x%x) cred failed",
doors->id, thr_self()));
switch (errno) {
case EINVAL:
/*
* This can happen if client is aborted between start
* of door call and here.... Just ignore the request
* (thr_exit??).
*/
retData = nullRetData;
break;
default:
ABORT_WITH_ERRNO(errno, "door_cred");
break;
}
} else {
CHECK_IF_ERRNO(mutex_lock(&doors->lock));
if (doors->doingShutdown && cred.dc_pid == doorsPid) {
/*
* If doing shutdown, request is from ourself, then
* terminate this thread. See doorsFree().
*/
doors->threadCount -= 1;
ASSERT(doors->threadCount >= 0);
LOG_DBG(('r', "doorsServerFunc(0x%llx, 0x%x) thr_exit count %d",
doors->id, thr_self(), doors->threadCount));
CHECK_IF_ERRNO(mutex_unlock(&doors->lock));
thr_exit(NULL);
}
LOG_DBGC((doors->doTrace, 'r',
"doorsServerFunc(0x%llx, 0x%x) do request",
doors->id, thr_self()));
CHECK_IF_ERRNO(mutex_unlock(&doors->lock));
retData = (*doors->serverFunc)(doors->delegate, doors, argp,
argSize, descp, nDesc, &cred);
}
}
ABORT_ON_ERRNO(door_return((char *)retData.dataPtr, retData.dataSize,
retData.descPtr, retData.nDesc));
}
/*************************************************************************
* Private Functions
*************************************************************************/
static void
doorsThreadCreate(/*const*/ door_info_t *dip)
{
Doors doors = (Doors) dip->di_data;
CHECK_IF_ERRNO(mutex_lock(&doors->lock));
LOG_DBG(('r', "doorsThreadCreate(0x%llx, 0x%x)", doors->id, thr_self()));
if (doors->threadCount >= doors->maxThreadCount || doors->doingShutdown) {
LOG_DBG(('r', "doorsThreadCreate(0x%llx, 0x%x) rejected count %d",
doors->id, thr_self(), doors->threadCount));
CHECK_IF_ERRNO(mutex_unlock(&doors->lock));
return;
}
doors->threadCount += 1;
LOG_DBG(('r', "doorsThreadCreate(0x%llx, 0x%x) accepted count %d",
doors->id, thr_self(), doors->threadCount));
#if DOORS_BUG2
doors->pendingCreates += 1;
#endif /* DOORS_BUG2 */
CHECK_IF_ERRNO(mutex_unlock(&doors->lock));
ABORT_IF_ERRNO(thr_create(NULL, doors->stackSize, doorsThreadInit, doors,
THR_BOUND | THR_DETACHED, NULL));
}
/* ARGSUSED1 */
static void
doorsCommandImpl(Actor actor, void *implArg)
{
while (actorIsRunning(actor)) {
Action action = actorGetAction(actor, NULL);
if (action != NULL) {
DoorsParameters *p = (DoorsParameters *)actionGetParameterp(action);
Doors doors = p->doors;
switch (p->command) {
case DOORS_COMMAND_NO_CLIENT:
/*
* We expect the noClientFunc to do a doorsFree
*/
(*doors->noClientFunc)(doors->delegate);
actionDone(action);
break;
default:
ABORT("unknown doorsCommand");
}
}
}
}
static void
doorBufferFree(void *arg)
{
DoorBuffer *dbp = (DoorBuffer *)arg;
if (dbp->body != NULL) {
free(dbp->body);
}
free(dbp);
}
#endif /* !defined(DOORS_HEADER) */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?