doors.c
来自「Sun公司Dream项目」· C语言 代码 · 共 679 行 · 第 1/2 页
C
679 行
/*
* The contents of this file are subject to the terms
* of the Common Development and Distribution License
* (the "License"). You may not use this file except
* in compliance with the License.
*
* You can obtain a copy of the license at
* http://www.opensource.org/licenses/cddl1.php
* See the License for the specific language governing
* permissions and limitations under the License.
*
* When distributing Covered Code, include this CDDL
* HEADER in each file and include the License file at
* http://www.opensource.org/licenses/cddl1.php. If
* applicable, add the following below this CDDL HEADER,
* with the fields enclosed by brackets "[]" replaced
* with your own identifying information:
* Portions Copyright [yyyy]
* [name of copyright owner]
*/
/*
* $(@)Doors.c $Revision: 1.2 $ $Date: 2006/07/15 00:02:33 $
*
* Copyright 2006 Sun Microsystems, Inc. All Rights Reserved.
*/
/*
* Copyright (c) 1998 by Sun Microsystems, Inc.
*/
/*
* Doors.c -- Object wrapper for Doors RPC.
*/
/*
* FIXME: Make sure client checks for need to munmap returned data.
*/
#pragma ident "@(#)Doors.c 1.9 99/10/27 SMI"
#if !defined(DOORS_HEADER)
#define DOORS_BODY
#define DOORS_INLINE extern
#include "cobjs/Doors.h"
#endif /* !defined(DOORS_HEADER) */
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <door.h>
#include <errno.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <synch.h>
#include <thread.h>
#include <unistd.h>
#include "cobjs/Actor.h"
#include "cobjs/Log.h"
#include "cobjs/Macros.h"
#include "cobjs/Types.h"
/*************************************************************************
* Defines
*************************************************************************/
/*
* WORKAROUND for libdoor bug. libdoor should pass the door fd to
* the thread_create func so it could store it somewhere the thread_init_func
* could find it. It doesn't, so we're forced to yield() until the
* door_create thread can set it.
*/
#define DOORS_BUG 1
/*
* WORKAROUND for libdoor bug. There's no clean mechanism for shutting
* down private door threads (ideally, doing a door_revoke() would cause
* private threads to thr_exit() when they re-entered the private pool).
* The first workaround was to do "self" door calls that were specially
* detected in the server func as close shutdowns on the server thread.
* This works "most" of the time, but occasionally the kernel seems to
* block this self door_call even though a thread still exists. This
* seems to happen mostly when the thread init call occurs close to
* the self door_call. The hack here is to ensure that all thread_init's
* (and the corresponding door_bind()) is done well before the self
* door_call.
*/
#define DOORS_BUG2 1
#define DOORS_DEFAULT_MAX_THREAD_COUNT 5
/*************************************************************************
* Instance Variables
*************************************************************************/
struct _Doors {
Object delegate;
DoorsThreadInitFunc threadInitFunc;
DoorsServerFunc serverFunc;
DoorsNoClientFunc noClientFunc;
size_t stackSize;
int maxThreadCount;
u_int attributes;
int fd;
door_id_t id;
char *file;
mutex_t lock;
#if DOORS_BUG
Boolean isInitialized;
cond_t initializedCond;
#endif /* DOORS_BUG */
#if DOORS_BUG2
cond_t pendingCond;
Boolean isPendingWait;
int pendingCreates;
#endif /* DOORS_BUG2 */
int threadCount;
Boolean doingNoClient;
Boolean doingShutdown;
Boolean doTrace;
};
/*************************************************************************
* Private types and prototypes referenced from inlines
*************************************************************************/
/*
* Use INLINE_PRIVATE if non-inline-able, define in Non-inlinable section
* Use static if inline-able, define in Private Inline-able section
*
* INLINE_PRIVATE void doorsInlinePrivate(void);
*/
typedef enum DoorsCommand {
DOORS_COMMAND_NO_CLIENT
} DoorsCommand;
typedef struct DoorsParameters {
DoorsCommand command;
Doors doors;
} DoorsParameters;
typedef struct DoorBuffer {
void *body;
size_t size;
} DoorBuffer;
/*************************************************************************
* Private class data referenced from inlines
*************************************************************************/
/*************************************************************************
* Inline Methods
*************************************************************************/
DOORS_INLINE door_id_t
doorsId(Doors doors)
{
return doors->id;
}
DOORS_INLINE int
doorsFd(Doors doors)
{
return doors->fd;
}
DOORS_INLINE int
doorsThreadCount(Doors doors)
{
return doors->threadCount;
}
DOORS_INLINE DoorsResultData
doorsResultData(void *datap, size_t dataSize, door_desc_t *descp, size_t nDesc)
{
DoorsResultData drd;
drd.dataPtr = datap;
drd.dataSize = dataSize;
drd.descPtr = descp;
drd.nDesc = nDesc;
return drd;
}
DOORS_INLINE unsigned long
doorsIdKeyHash(const void *key, unsigned int *rehashp)
{
door_id_t doorId = *(door_id_t *)key;
*rehashp = (unsigned int) ((doorId * 1103515245L + 12345) >> 16);
return ((unsigned long) (doorId * 123821)) >> 10;
}
DOORS_INLINE Boolean
doorsIdKeyIsEqual(const void *key1, const void *key2)
{
return Boolean( *(door_id_t *)key1 == *(door_id_t *)key2 );
}
DOORS_INLINE int
doorsIdKeyCmp(const void *key1, const void *key2)
{
return *(door_id_t *)key1 - *(door_id_t *)key2;
}
/* ARGSUSED1 */
DOORS_INLINE const void *
doorsIdKeyDup(const void *key, const void *value)
{
door_id_t *newIdp = NEW(door_id_t, 1);
*newIdp = *(door_id_t *)key;
return newIdp;
}
DOORS_INLINE void
doorsIdKeyFree(void *key)
{
free(key);
}
/*************************************************************************
* Private Inlineable Methods and Functions Called From Inlines
*************************************************************************/
#if !defined(DOORS_HEADER)
/*************************************************************************
* Private types
*************************************************************************/
/*************************************************************************
* Private method prototypes
*************************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
static void *doorsThreadInit(void *arg);
static void doorsServerFunc(void *cookie, /*const void*/ char *argp, size_t argSize,
/*const*/ door_desc_t *descp, size_t nDesc);
/*************************************************************************
* Private function prototypes
*************************************************************************/
static void doorsThreadCreate(/*const*/ door_info_t *dip);
static void doorsCommandImpl(Actor actor, void *implArg);
static void doorBufferFree(void *arg);
#ifdef __cplusplus
}
#endif
/*************************************************************************
* Private class data
*************************************************************************/
static DoorsResultData nullRetData = { NULL, 0, NULL, 0};
static Actor commandActor;
static thread_key_t resultBufferKey;
static thread_key_t descBufferKey;
static Action noClientAction;
static pid_t doorsPid;
/*************************************************************************
* Class Methods
*************************************************************************/
void
doorsInit(void)
{
doorsPid = getpid();
(void) door_server_create(doorsThreadCreate);
noClientAction = NEW_ACTION(DoorsParameters, NULL);
commandActor = actorNew(doorsCommandImpl, NULL, NULL, NULL, 0,
ACTOR_TYPE_LWP);
ABORT_IF_ERRNO(thr_keycreate(&resultBufferKey, doorBufferFree));
ABORT_IF_ERRNO(thr_keycreate(&descBufferKey, doorBufferFree));
}
void
doorsFini(void)
{
actorFree(commandActor);
actionFree(noClientAction);
}
Doors
doorsNew(Object delegate, DoorsThreadInitFunc threadInitFunc,
DoorsServerFunc serverFunc, DoorsNoClientFunc noClientFunc,
size_t stackSize, int maxThreadCount)
{
Doors doors = NEW_ZEROED(struct _Doors, 1);
door_info_t info;
if (maxThreadCount == 0) {
maxThreadCount = DOORS_DEFAULT_MAX_THREAD_COUNT;
}
if (commandActor == NULL) {
ABORT("doorsInit not called");
}
doors->delegate = delegate;
doors->threadInitFunc = threadInitFunc;
doors->serverFunc = serverFunc;
doors->noClientFunc = noClientFunc;
doors->stackSize = stackSize;
doors->maxThreadCount = maxThreadCount;
/*
* You MUST have private threads until door_revoke() can block
* until no thread active on door.
*/
doors->attributes = DOOR_PRIVATE;
if (noClientFunc != NULL) {
doors->attributes |= DOOR_UNREF;
}
CHECK_IF_ERRNO(mutex_init(&doors->lock, USYNC_THREAD, 0));
doors->threadCount = 0;
doors->doingShutdown = FALSE;
doors->doingNoClient = FALSE;
doors->doTrace = FALSE;
#if DOORS_BUG
CHECK_IF_ERRNO(cond_init(&doors->initializedCond, USYNC_THREAD, 0));
doors->isInitialized = FALSE;
#endif /* DOORS_BUG */
#if DOORS_BUG2
CHECK_IF_ERRNO(cond_init(&doors->pendingCond, USYNC_THREAD, 0));
doors->pendingCreates = 0;
doors->isPendingWait = FALSE;
#endif /* DOORS_BUG2 */
LOG_DBG(('r', "doorsNew(0x%llx, 0x%x)", doors->id, thr_self()));
ABORT_ON_ERRNO(doors->fd = door_create(doorsServerFunc, doors,
doors->attributes));
ABORT_ON_ERRNO(door_info(doors->fd, &info));
doors->id = info.di_uniquifier;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?