door_xcreate(3DOOR) Door Library Functions door_xcreate(3DOOR)NAMEdoor_xcreate - create a door descriptor for a private door with per-
door control over thread creation
SYNOPSIS
#include <door.h>
typedef void door_server_procedure_t(void *, char *, size_t,
door_desc_t *, uint_t);
typedef int door_xcreate_server_func_t(door_info_t *,
void *(*)(void *), void *, void *);
typedef void door_xcreate_thrsetup_func_t(void *);
int door_xcreate(door_server_procedure_t *server_proceduere,
void *cookie, uint_t attributes,
door_xcreate_server_func_t *thr_create_func,
door_xcreate_thrsetup_func_t *thr_setup_func, void *crcookie,
int nthread);
DESCRIPTION
The door_xcreate() function creates a private door to the given
server_procedure, with per-door control over the creation of threads
that will service invocations of that door. A private door is a door
that has a private pool of threads that service calls to that door
alone; non-private doors share a pool of service threads (see door_cre‐
ate(3DOOR)).
Creating private doors using door_create()
Prior to the introduction of door_xcreate(), a private door was created
using door_create() specifying attributes including DOOR_PRIVATE after
installing a suitable door server thread creation function using
door_server_create(). During such a call to door_create(), the first
server thread for that door is created by calling the door server func‐
tion; you must therefore already have installed a custom door server
creation function using door_server_create(). The custom server cre‐
ation function is called at initial creation of a private door, and
again whenever a new invocation uses the last available thread for that
door. The function must decide whether it wants to increase the level
of concurrency by creating an additional thread - if it decides not to
then further invocations may have to wait for an existing active invo‐
cation to complete before they can proceed. Additional threads may be
created using whatever thread attributes are desired in the applica‐
tion, and the application must specify a thread start function (to
thr_create(3C) or pthread_create(3C)) which will perform a door_bind()
to the newly-created door before calling door_return(NULL, 0, NULL, 0)
to enter service. See door_server_create(3DOOR) and door_bind(3DOOR)
for more information and for an example.
This "legacy" private door API is adequate for many uses, but has some
limitations:
o The server thread creation function appointed via the
door_server_create() is shared by all doors in the process.
Private doors are distinguished from non-private in that the
door_info_t pointer argument to the thread creation function
is non-null for private doors; from the door_info_t the
associated door server procedure is available via the
di_proc member.
o If a library wishes to create a private door of which the
application is essentially unaware it has no option but to
inherit any function appointed with door_server_create()
which may render the library door inoperable.
o Newly-created server threads must bind to the door they will
service, but the door file descriptor to quote in
door_bind() is not available in the door_info_t structure we
receive a pointer to. The door file descriptor is returned
as the result of door_create(), but the initial service
thread is created during the call to door_create(). This
leads to complexity in the startup of the service thread,
and tends to force the use of global variables for the door
file descriptors as per the example in door_bind().
Creating private doors with door_xcreate()
The door_xcreate() function is purpose-designed for the creation of
private doors and simplifies their use by moving responsibility for
binding the new server thread and synchronizing with it into a library-
provided thread startup function:
o The first three arguments to door_xcreate() are as you would
use in door_create(): the door server_procedure, a private
cookie to pass to that procedure whenever it is invoked for
this door, and desired door attributes. The DOOR_PRIVATE
attribute is implicit, and an additional attribute of
DOOR_NO_DEPLETION_CB is available.
o Four additional arguments specify a server thread creation
function to use for this door (must not be NULL), a thread
setup function for new server threads (can be NULL), a
cookie to pass to those functions, and the initial number of
threads to create for this door.
o The door_xcreate_server_func_t() for creating server threads
has differing semantics to those of a door_server_func_t()
used in door_server_create(). In addition to a door_info_t
pointer it also receives as arguments a library-provided
thread start function and thread start argument that it must
use, and the private cookie registered in the call to
door_xcreate(). The nominated door_xcreate_server_func_t()
must:
o Return 0 if no additional thread is to be created, for
example if it decides the current level of concurrency
is sufficient. When the server thread creation function
is invoked as part of a depletion callback (as opposed
to during initial door_xcreate()) the door_info_t
di_attributes member includes DOOR_DEPLETION_CB.
o Otherwise attempt to create exactly one new thread using
thr_create() or pthread_create(), with whatever thread
attributes (stack size) are desired and quoting the
implementation-provided thread start function and opaque
data cookie. If the call to thr_create() or pthread_cre‐
ate() is successful then return 1, otherwise return -1.
o Do not call door_bind() or request to enter service via
door_return(NULL, 0, NULL, 0).
As in door_server_create() new server threads must be created
PTHREAD_SCOPE_SYSTEM and PTHREAD_CREATE_DETACHED for POSIX threads,
and THR_BOUND and THR_DETACHED for Solaris threads. The signal dis‐
position and scheduling class of newly-created threads are inher‐
ited from the calling thread, initially from the thread calling
door_xcreate() and subsequently from the current active door server
thread.
o The library-provided thread start function performs the fol‐
lowing operations in the order presented:
o Calls the door_xcreate_thrsetup_func_t() if it is not
NULL, passing the crcookie. You can use this setup func‐
tion to perform custom service thread configuration that
must be done from the context of the new thread. Typi‐
cally this is to configure cancellation preferences, and
possibly to associate application thread-specific-data
with the newly-created server thread.
If thr_setup_func() was NULL then a default is applied
which will configure the new thread with pthread_set‐
cancelstate(PTHREAD_CANCEL_DISABLE, NULL) and
pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL). If
the server code is truly interested in notifications of
client aborts during a door invocation then you will
need to provide a thr_setup_func() that does not disable
cancellations, and use pthread_cleanup_push(3C)and
pthread_cleanup_pop(3C)as appropriate.
o Binds the new thread to the door file descriptor using
door_bind().
o Synchronizes with door_xcreate() so that the new server
thread is known to have successfully completed
door_bind() before door_xcreate() returns.
o The number of service threads to create at initial door cre‐
ation time can be controlled through the nthread argument to
door_xcreate(). The nominated door_xcreate_server_func_t()
will be called nthread times. All nthread new server threads
must be created successfully (thr_create_func() returns 1
for each) and all must succeed in binding to the new door;
if fewer than nthread threads are created, or fewer than
nthread succeed in binding, then door_xcreate() fails and
any threads that were created are made to exit.
No artificial maximum value is imposed on the nthread argu‐
ment: it may be as high as system resources and available
virtual memory permit. There is a small amount of additional
stack usage in the door_xcreate() stack frame for each
thread - up to 16 bytes in a 64-bit application. If there is
unsufficient room to extend the stack for this purpose then
door_xcreate() fails with E2BIG.
The door attributes that can be selected in the call to
door_xcreate() are the same as in door_create(), with
DOOR_PRIVATE implied and DOOR_NO_DEPLETION_CB added:
DOOR_PRIVATE
It is not necessary to include this attribute. The
door_xcreate() interfaces only creates private doors.
DOOR_NO_DEPLETION_CB
Create the initial pool of nthread service threads, but
do not perform further callbacks to the thr_cre‐
ate_func() for this door when the thread pool appears to
be depleted at the start of a new door invocation. This
allows you to select a fixed level of concurrency.
Another di_attribute is defined during thread depletion
callbacks:
DOOR_DEPLETION_CB
This call to the server thread creation function is the
result of a depletion callback. This attribute is not
set when the function is called during initial
door_xcreate().
The descriptor returned from door_xcreate() will be marked as close on
exec (FD_CLOEXEC). Information about a door is available for all
clients of a door using door_info(3DOOR). Applications concerned with
security should not place secure information in door data that is
accessible by door_info(). In particular, secure data should not be
stored in the data item cookie.
A process can advertise a door in the file system name space using fat‐
tach(3C).
A door created with door_xcreate() may be revoked using
door_revoke(3DOOR). This closes the associated file descriptor, and
acts as a barrier to further door invocations, but existing active
invocations are not guaranteed to have completed before door_revoke()
returns. Server threads bound to a revoked door do not wakeup or exit
automatically when the door is revoked.
RETURN VALUES
Upon successful completion, door_xcreate() returns a non-negative
value. Otherwise, door_xcreate() returns -1 and sets errno to indicate
the error.
ERRORS
The door_xcreate() function will fail if:
E2BIG The requested nthread is too large. A small amount of stack
space is required for each thread we must start and synchro‐
nize with. If extending the door_xcreate() stack by the
required amount will exceed the stack bounds then E2BIG is
returned.
EBADF The attempt to door_bind() within the library-provided
thread start function failed.
EINVAL Invalid attributes are passed, nthread is less than 1, or
thr_create_func() is NULL. This is also returned if thr_cre‐
ate_func() returns 0 (no thread creation attempted) during
door_xcreate().
EMFILE The process has too many open descriptors.
ENOMEM Insufficient memory condition while creating the door.
ENOTSUP A door_xcreate() call was attempted from a fork handler.
EPIPE A call to the nominated thr_create_func() returned -1 indi‐
cating that pthread_create() or thr_create() failed.
EXAMPLES
Example 1 Create a private door with an initial pool of 10 server
threads
Create a private door with an initial pool of 10 server threads.
Threads are created with the minimum required attributes and there is
no thread setup function. Use fattach() to advertise the door in the
filesystem namespace.
static pthread_attr_t tattr;
/*
* Simplest possible door_xcreate_server_func_t. Always attempt to
* create a thread, using the previously initialized attributes for
* all threads. We must use the start function and argument provided,
* and make no use of our private mycookie argument.
*/
int
thrcreatefunc(door_info_t *dip, void *(*startf)(void *),
void *startfarg, void *mycookie)
{
if (pthread_create(NULL, &tattr, startf, startfarg) != 0) {
perror("thrcreatefunc: pthread_create");
return (-1);
}
return (1);
}
/*
* Dummy door server procedure - does no processing.
*/
void
door_proc(void *cookie, char *argp, size_t argsz, door_desc_t *descp,
uint_t n)
{
door_return (NULL, 0, NULL, 0);
}
int
main(int argc, char *argv[])
{
struct stat buf;
int did;
/*
* Setup thread attributes - minimum required.
*/
(void) pthread_attr_init(&tattr);
(void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
(void) pthread_attr_setscope(&tattr, PTHREAD_SCOPE_SYSTEM);
/*
* Create a private door with an initial pool of 10 server threads.
*/
did = door_xcreate(door_proc, NULL, 0, thrcreatefunc, NULL, NULL,
10);
if (did == -1) {
perror("door_xcreate");
exit(1);
}
if (stat(DOORPATH, &buf) < 0) {
int newfd;
if ((newfd = creat(DOORPATH, 0644)) < 0) {
perror("creat");
exit(1);
}
(void) close(newfd);
}
(void) fdetach(DOORPATH);
(void) fdetach(DOORPATH);
if (fattach(did, DOORPATH) < 0) {
perror("fattach");
exit(1);
}
(void) fprintf(stderr, "Pausing in main0);
(void) pause();
}
Example 2 Create a private door with exactly one server thread and no
callbacks for additional threads
Create a private door with exactly one server thread and no callbacks
for additional threads. Use a server thread stacksize of 32K, and
specify a thread setup function.
#define DOORPATH "/tmp/grmdoor"
static pthread_attr_t tattr;
/*
* Thread setup function - configuration that must be performed from
* the conext of the new thread. The mycookie argument is the
* second-to-last argument from door_xcreate.
*/
void
thrsetupfunc(void *mycookie)
{
/*
* If a thread setup function is specified it must do the
* following at minimum.
*/
(void) pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
/*
* The default thread setup functions also performs the following
* to disable thread cancellation notifications, so that server
* threads are not cancelled when a client aborts a door call.
* This is not a requirement.
*/
(void) pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
/*
* Now we can go on to perform other thread initialization,
* for example to allocate and initialize some thread-specific data
* for this thread; for thread-specific data you can use a
destructor function in pthread_key_create if you want to perform
any actions if/when a door server thread exits.
*/
}
/*
* The door_xcreate_server_func_t we will use for server thread
* creation. The mycookie argument is the second-to-last argument
* from door_xcreate.
*/
int
thrcreatefunc(door_info_t *dip, void *(*startf)(void *),
void *startfarg, void *mycookie)
{
if (pthread_create(NULL, &tattr, startf, startfarg) != 0) {
perror("thrcreatefunc: pthread_create");
return (-1);
}
return (1);
}
/*
* Door procedure. The cookie received here is the second arg to
* door_xcreate.
*/
void
door_proc(void *cookie, char *argp, size_t argsz, door_desc_t *descp,
uint_t n)
{
(void) door_return(NULL, 0, NULL, 0);
}
int
main(int argc, char *argv[])
{
struct stat buf;
int did;
/*
* Configure thread attributes we will use in thrcreatefunc.
* The PTHREAD_CREATE_DETACHED and PTHREAD_SCOPE_SYSTEM are
* required.
*/
(void) pthread_attr_init(&tattr);
(void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
(void) pthread_attr_setscope(&tattr, PTHREAD_SCOPE_SYSTEM);
(void) pthread_attr_setstacksize(&tattr, 16 * 1024);
/*
* Create a private door with just one server thread and asking for
* no further callbacks on thread pool depletion during an
* invocation.
*/
did = door_xcreate(door_proc, NULL, DOOR_NO_DEPLETION_CB,
thrcreatefunc, thrsetupfunc, NULL, 1);
if (did == -1) {
perror("door_xcreate");
exit(1);
}
if (stat(DOORPATH, &buf) < 0) {
int newfd;
if ((newfd = creat(DOORPATH, 0644)) < 0) {
perror("creat");
exit(1);
}
(void) close(newfd);
}
(void) fdetach(DOORPATH);
if (fattach(did, DOORPATH) < 0) {
perror("fattach");
exit(1);
}
(void) fprintf(stderr, "Pausing in main0);
(void) pause();
}
ATTRIBUTES
See attributes(5) for descriptions of the following attributes:
┌─────────────────────────────┬─────────────────────────────┐
│ ATTRIBUTE TYPE │ ATTRIBUTE VALUE │
├─────────────────────────────┼─────────────────────────────┤
│Architecture │all │
├─────────────────────────────┼─────────────────────────────┤
│Availability │SUNWcsu │
├─────────────────────────────┼─────────────────────────────┤
│Interface Stability │Committed │
├─────────────────────────────┼─────────────────────────────┤
│MT-Level │Safe │
└─────────────────────────────┴─────────────────────────────┘
SEE ALSOdoor_bind(3DOOR), door_call(3DOOR), door_create(3DOOR),
door_info(3DOOR), door_revoke(3DOOR), door_server_create(3DOOR), fat‐
tach(3C), libdoor(3LIB), pthread_create(3C), pthread_cleanup_pop(3C),
pthread_cleanup_push(3C), thr_create(3C), attributes(5), cancella‐
tion(5)SunOS 5.10 19 Apr 2010 door_xcreate(3DOOR)