|
@@ -7,29 +7,39 @@
|
|
|
#include <sys/types.h>
|
|
#include <sys/types.h>
|
|
|
#include <sys/wait.h>
|
|
#include <sys/wait.h>
|
|
|
#include <errno.h>
|
|
#include <errno.h>
|
|
|
|
|
+#include <assert.h>
|
|
|
#include <err.h>
|
|
#include <err.h>
|
|
|
#include "antithread.h"
|
|
#include "antithread.h"
|
|
|
#include <ccan/noerr/noerr.h>
|
|
#include <ccan/noerr/noerr.h>
|
|
|
#include <ccan/talloc/talloc.h>
|
|
#include <ccan/talloc/talloc.h>
|
|
|
#include <ccan/read_write_all/read_write_all.h>
|
|
#include <ccan/read_write_all/read_write_all.h>
|
|
|
#include <ccan/alloc/alloc.h>
|
|
#include <ccan/alloc/alloc.h>
|
|
|
|
|
+#include <ccan/list/list.h>
|
|
|
|
|
|
|
|
/* FIXME: Valgrind support should be possible for some cases. Tricky
|
|
/* FIXME: Valgrind support should be possible for some cases. Tricky
|
|
|
* case is where another process allocates for you, but at worst we
|
|
* case is where another process allocates for you, but at worst we
|
|
|
* could reset what is valid and what isn't on every entry into the
|
|
* could reset what is valid and what isn't on every entry into the
|
|
|
* library or something. */
|
|
* library or something. */
|
|
|
|
|
|
|
|
-struct at_pool
|
|
|
|
|
-{
|
|
|
|
|
- const void *ctx;
|
|
|
|
|
|
|
+static LIST_HEAD(pools);
|
|
|
|
|
+
|
|
|
|
|
+/* Talloc destroys parents before children (damn Tridge's failing destructors!)
|
|
|
|
|
+ * so we need the first child (ie. last-destroyed) to actually clean up. */
|
|
|
|
|
+struct at_pool_contents {
|
|
|
|
|
+ struct list_node list;
|
|
|
void *pool;
|
|
void *pool;
|
|
|
unsigned long poolsize;
|
|
unsigned long poolsize;
|
|
|
int fd;
|
|
int fd;
|
|
|
int parent_rfd, parent_wfd;
|
|
int parent_rfd, parent_wfd;
|
|
|
|
|
+ struct at_pool *atp;
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
-struct athread
|
|
|
|
|
-{
|
|
|
|
|
|
|
+struct at_pool {
|
|
|
|
|
+ struct at_pool_contents *p;
|
|
|
|
|
+ const void *ctx;
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+struct athread {
|
|
|
pid_t pid;
|
|
pid_t pid;
|
|
|
int rfd, wfd;
|
|
int rfd, wfd;
|
|
|
};
|
|
};
|
|
@@ -64,13 +74,39 @@ static void unlock(int fd, unsigned long off)
|
|
|
errno = serrno;
|
|
errno = serrno;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+/* This pointer is in a pool. Find which one. */
|
|
|
|
|
+static struct at_pool_contents *find_pool(const void *ptr)
|
|
|
|
|
+{
|
|
|
|
|
+ struct at_pool_contents *p;
|
|
|
|
|
+
|
|
|
|
|
+ list_for_each(&pools, p, list) {
|
|
|
|
|
+ /* Special case for initial allocation: ptr *is* pool */
|
|
|
|
|
+ if (ptr == p->atp)
|
|
|
|
|
+ return p;
|
|
|
|
|
+
|
|
|
|
|
+ if ((char *)ptr >= (char *)p->pool
|
|
|
|
|
+ && (char *)ptr < (char *)p->pool + p->poolsize)
|
|
|
|
|
+ return p;
|
|
|
|
|
+ }
|
|
|
|
|
+ abort();
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static int destroy_pool(struct at_pool_contents *p)
|
|
|
|
|
+{
|
|
|
|
|
+ list_del(&p->list);
|
|
|
|
|
+ munmap(p->pool, p->poolsize);
|
|
|
|
|
+ close(p->fd);
|
|
|
|
|
+ close(p->parent_rfd);
|
|
|
|
|
+ close(p->parent_wfd);
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
static void *at_realloc(const void *parent, void *ptr, size_t size)
|
|
static void *at_realloc(const void *parent, void *ptr, size_t size)
|
|
|
{
|
|
{
|
|
|
- struct at_pool *p = talloc_find_parent_bytype(parent, struct at_pool);
|
|
|
|
|
|
|
+ struct at_pool_contents *p = find_pool(parent);
|
|
|
/* FIXME: realloc in ccan/alloc? */
|
|
/* FIXME: realloc in ccan/alloc? */
|
|
|
void *new;
|
|
void *new;
|
|
|
|
|
|
|
|
- lock(p->fd, 0);
|
|
|
|
|
if (size == 0) {
|
|
if (size == 0) {
|
|
|
alloc_free(p->pool, p->poolsize, ptr);
|
|
alloc_free(p->pool, p->poolsize, ptr);
|
|
|
new = NULL;
|
|
new = NULL;
|
|
@@ -89,10 +125,28 @@ static void *at_realloc(const void *parent, void *ptr, size_t size)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
- unlock(p->fd, 0);
|
|
|
|
|
|
|
+
|
|
|
return new;
|
|
return new;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+static struct at_pool_contents *locked;
|
|
|
|
|
+static void talloc_lock(const void *ptr)
|
|
|
|
|
+{
|
|
|
|
|
+ struct at_pool_contents *p = find_pool(ptr);
|
|
|
|
|
+
|
|
|
|
|
+ lock(p->fd, 0);
|
|
|
|
|
+ assert(!locked);
|
|
|
|
|
+ locked = p;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static void talloc_unlock(void)
|
|
|
|
|
+{
|
|
|
|
|
+ struct at_pool_contents *p = locked;
|
|
|
|
|
+
|
|
|
|
|
+ locked = NULL;
|
|
|
|
|
+ unlock(p->fd, 0);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
/* We add 16MB to size. This compensates for address randomization. */
|
|
/* We add 16MB to size. This compensates for address randomization. */
|
|
|
#define PADDING (16 * 1024 * 1024)
|
|
#define PADDING (16 * 1024 * 1024)
|
|
|
|
|
|
|
@@ -100,7 +154,8 @@ static void *at_realloc(const void *parent, void *ptr, size_t size)
|
|
|
struct at_pool *at_pool(unsigned long size)
|
|
struct at_pool *at_pool(unsigned long size)
|
|
|
{
|
|
{
|
|
|
int fd;
|
|
int fd;
|
|
|
- struct at_pool *p;
|
|
|
|
|
|
|
+ struct at_pool *atp;
|
|
|
|
|
+ struct at_pool_contents *p;
|
|
|
FILE *f;
|
|
FILE *f;
|
|
|
|
|
|
|
|
/* FIXME: How much should we actually add for overhead?. */
|
|
/* FIXME: How much should we actually add for overhead?. */
|
|
@@ -122,10 +177,14 @@ struct at_pool *at_pool(unsigned long size)
|
|
|
if (ftruncate(fd, size + PADDING) != 0)
|
|
if (ftruncate(fd, size + PADDING) != 0)
|
|
|
goto fail_close;
|
|
goto fail_close;
|
|
|
|
|
|
|
|
- p = talloc(NULL, struct at_pool);
|
|
|
|
|
- if (!p)
|
|
|
|
|
|
|
+ atp = talloc(NULL, struct at_pool);
|
|
|
|
|
+ if (!atp)
|
|
|
goto fail_close;
|
|
goto fail_close;
|
|
|
|
|
|
|
|
|
|
+ atp->p = p = talloc(NULL, struct at_pool_contents);
|
|
|
|
|
+ if (!p)
|
|
|
|
|
+ goto fail_free;
|
|
|
|
|
+
|
|
|
/* First map gets a nice big area. */
|
|
/* First map gets a nice big area. */
|
|
|
p->pool = mmap(NULL, size+PADDING, PROT_READ|PROT_WRITE, MAP_SHARED, fd,
|
|
p->pool = mmap(NULL, size+PADDING, PROT_READ|PROT_WRITE, MAP_SHARED, fd,
|
|
|
0);
|
|
0);
|
|
@@ -139,22 +198,22 @@ struct at_pool *at_pool(unsigned long size)
|
|
|
if (p->pool == MAP_FAILED)
|
|
if (p->pool == MAP_FAILED)
|
|
|
goto fail_free;
|
|
goto fail_free;
|
|
|
|
|
|
|
|
- /* FIXME: Destructor? */
|
|
|
|
|
p->fd = fd;
|
|
p->fd = fd;
|
|
|
p->poolsize = size;
|
|
p->poolsize = size;
|
|
|
p->parent_rfd = p->parent_wfd = -1;
|
|
p->parent_rfd = p->parent_wfd = -1;
|
|
|
|
|
+ p->atp = atp;
|
|
|
alloc_init(p->pool, p->poolsize);
|
|
alloc_init(p->pool, p->poolsize);
|
|
|
|
|
+ list_add(&pools, &p->list);
|
|
|
|
|
+ talloc_set_destructor(p, destroy_pool);
|
|
|
|
|
|
|
|
- p->ctx = talloc_add_external(p, at_realloc);
|
|
|
|
|
- if (!p->ctx)
|
|
|
|
|
- goto fail_unmap;
|
|
|
|
|
-
|
|
|
|
|
- return p;
|
|
|
|
|
|
|
+ atp->ctx = talloc_add_external(atp,
|
|
|
|
|
+ at_realloc, talloc_lock, talloc_unlock);
|
|
|
|
|
+ if (!atp->ctx)
|
|
|
|
|
+ goto fail_free;
|
|
|
|
|
+ return atp;
|
|
|
|
|
|
|
|
-fail_unmap:
|
|
|
|
|
- munmap(p->pool, size);
|
|
|
|
|
fail_free:
|
|
fail_free:
|
|
|
- talloc_free(p);
|
|
|
|
|
|
|
+ talloc_free(atp);
|
|
|
fail_close:
|
|
fail_close:
|
|
|
close_noerr(fd);
|
|
close_noerr(fd);
|
|
|
return NULL;
|
|
return NULL;
|
|
@@ -190,17 +249,18 @@ static int destroy_at(struct athread *at)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/* Sets up thread and forks it. NULL on error. */
|
|
/* Sets up thread and forks it. NULL on error. */
|
|
|
-static struct athread *fork_thread(struct at_pool *pool)
|
|
|
|
|
|
|
+static struct athread *fork_thread(struct at_pool *atp)
|
|
|
{
|
|
{
|
|
|
int p2c[2], c2p[2];
|
|
int p2c[2], c2p[2];
|
|
|
struct athread *at;
|
|
struct athread *at;
|
|
|
|
|
+ struct at_pool_contents *pool = atp->p;
|
|
|
|
|
|
|
|
/* You can't already be a child of this pool. */
|
|
/* You can't already be a child of this pool. */
|
|
|
if (pool->parent_rfd != -1)
|
|
if (pool->parent_rfd != -1)
|
|
|
errx(1, "Can't create antithread on this pool: we're one");
|
|
errx(1, "Can't create antithread on this pool: we're one");
|
|
|
|
|
|
|
|
/* We don't want this allocated *in* the pool. */
|
|
/* We don't want this allocated *in* the pool. */
|
|
|
- at = talloc_steal(pool, talloc(NULL, struct athread));
|
|
|
|
|
|
|
+ at = talloc_steal(atp, talloc(NULL, struct athread));
|
|
|
|
|
|
|
|
if (pipe(p2c) != 0)
|
|
if (pipe(p2c) != 0)
|
|
|
goto free;
|
|
goto free;
|
|
@@ -241,19 +301,19 @@ free:
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/* Creating an antithread via fork() */
|
|
/* Creating an antithread via fork() */
|
|
|
-struct athread *_at_run(struct at_pool *pool,
|
|
|
|
|
|
|
+struct athread *_at_run(struct at_pool *atp,
|
|
|
void *(*fn)(struct at_pool *, void *),
|
|
void *(*fn)(struct at_pool *, void *),
|
|
|
void *obj)
|
|
void *obj)
|
|
|
{
|
|
{
|
|
|
struct athread *at;
|
|
struct athread *at;
|
|
|
|
|
|
|
|
- at = fork_thread(pool);
|
|
|
|
|
|
|
+ at = fork_thread(atp);
|
|
|
if (!at)
|
|
if (!at)
|
|
|
return NULL;
|
|
return NULL;
|
|
|
|
|
|
|
|
if (at->pid == 0) {
|
|
if (at->pid == 0) {
|
|
|
/* Child */
|
|
/* Child */
|
|
|
- at_tell_parent(pool, fn(pool, obj));
|
|
|
|
|
|
|
+ at_tell_parent(atp, fn(atp, obj));
|
|
|
exit(0);
|
|
exit(0);
|
|
|
}
|
|
}
|
|
|
/* Parent */
|
|
/* Parent */
|
|
@@ -269,12 +329,12 @@ static unsigned int num_args(char *const argv[])
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/* Fork and execvp, with added arguments for child to grab. */
|
|
/* Fork and execvp, with added arguments for child to grab. */
|
|
|
-struct athread *at_spawn(struct at_pool *pool, void *arg, char *cmdline[])
|
|
|
|
|
|
|
+struct athread *at_spawn(struct at_pool *atp, void *arg, char *cmdline[])
|
|
|
{
|
|
{
|
|
|
struct athread *at;
|
|
struct athread *at;
|
|
|
int err;
|
|
int err;
|
|
|
|
|
|
|
|
- at = fork_thread(pool);
|
|
|
|
|
|
|
+ at = fork_thread(atp);
|
|
|
if (!at)
|
|
if (!at)
|
|
|
return NULL;
|
|
return NULL;
|
|
|
|
|
|
|
@@ -283,15 +343,15 @@ struct athread *at_spawn(struct at_pool *pool, void *arg, char *cmdline[])
|
|
|
char *argv[num_args(cmdline) + 2];
|
|
char *argv[num_args(cmdline) + 2];
|
|
|
argv[0] = cmdline[0];
|
|
argv[0] = cmdline[0];
|
|
|
argv[1] = talloc_asprintf(NULL, "AT:%p/%lu/%i/%i/%i/%p",
|
|
argv[1] = talloc_asprintf(NULL, "AT:%p/%lu/%i/%i/%i/%p",
|
|
|
- pool->pool, pool->poolsize,
|
|
|
|
|
- pool->fd, pool->parent_rfd,
|
|
|
|
|
- pool->parent_wfd, arg);
|
|
|
|
|
|
|
+ atp->p->pool, atp->p->poolsize,
|
|
|
|
|
+ atp->p->fd, atp->p->parent_rfd,
|
|
|
|
|
+ atp->p->parent_wfd, arg);
|
|
|
/* Copy including NULL terminator. */
|
|
/* Copy including NULL terminator. */
|
|
|
memcpy(&argv[2], &cmdline[1], num_args(cmdline)*sizeof(char *));
|
|
memcpy(&argv[2], &cmdline[1], num_args(cmdline)*sizeof(char *));
|
|
|
execvp(argv[0], argv);
|
|
execvp(argv[0], argv);
|
|
|
|
|
|
|
|
err = errno;
|
|
err = errno;
|
|
|
- write_all(pool->parent_wfd, &err, sizeof(err));
|
|
|
|
|
|
|
+ write_all(atp->p->parent_wfd, &err, sizeof(err));
|
|
|
exit(1);
|
|
exit(1);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -344,7 +404,8 @@ void at_tell(struct athread *at, const void *status)
|
|
|
/* For child to grab arguments from command line (removes them) */
|
|
/* For child to grab arguments from command line (removes them) */
|
|
|
struct at_pool *at_get_pool(int *argc, char *argv[], void **arg)
|
|
struct at_pool *at_get_pool(int *argc, char *argv[], void **arg)
|
|
|
{
|
|
{
|
|
|
- struct at_pool *p = talloc(NULL, struct at_pool);
|
|
|
|
|
|
|
+ struct at_pool *atp = talloc(NULL, struct at_pool);
|
|
|
|
|
+ struct at_pool_contents *p;
|
|
|
void *map;
|
|
void *map;
|
|
|
int err;
|
|
int err;
|
|
|
|
|
|
|
@@ -357,6 +418,8 @@ struct at_pool *at_get_pool(int *argc, char *argv[], void **arg)
|
|
|
if (arg == NULL)
|
|
if (arg == NULL)
|
|
|
arg = ↦
|
|
arg = ↦
|
|
|
|
|
|
|
|
|
|
+ p = atp->p = talloc(atp, struct at_pool_contents);
|
|
|
|
|
+
|
|
|
if (sscanf(argv[1], "AT:%p/%lu/%i/%i/%i/%p",
|
|
if (sscanf(argv[1], "AT:%p/%lu/%i/%i/%i/%p",
|
|
|
&p->pool, &p->poolsize, &p->fd,
|
|
&p->pool, &p->poolsize, &p->fd,
|
|
|
&p->parent_rfd, &p->parent_wfd, arg) != 6) {
|
|
&p->parent_rfd, &p->parent_wfd, arg) != 6) {
|
|
@@ -375,8 +438,13 @@ struct at_pool *at_get_pool(int *argc, char *argv[], void **arg)
|
|
|
goto fail;
|
|
goto fail;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- p->ctx = talloc_add_external(p, at_realloc);
|
|
|
|
|
- if (!p->ctx)
|
|
|
|
|
|
|
+ list_add(&pools, &p->list);
|
|
|
|
|
+ talloc_set_destructor(p, destroy_pool);
|
|
|
|
|
+ p->atp = atp;
|
|
|
|
|
+
|
|
|
|
|
+ atp->ctx = talloc_add_external(atp,
|
|
|
|
|
+ at_realloc, talloc_lock, talloc_unlock);
|
|
|
|
|
+ if (!atp->ctx)
|
|
|
goto fail;
|
|
goto fail;
|
|
|
|
|
|
|
|
/* Tell parent we're good. */
|
|
/* Tell parent we're good. */
|
|
@@ -388,33 +456,33 @@ struct at_pool *at_get_pool(int *argc, char *argv[], void **arg)
|
|
|
|
|
|
|
|
/* Delete AT arg. */
|
|
/* Delete AT arg. */
|
|
|
memmove(&argv[1], &argv[2], --(*argc));
|
|
memmove(&argv[1], &argv[2], --(*argc));
|
|
|
- return p;
|
|
|
|
|
|
|
+
|
|
|
|
|
+ return atp;
|
|
|
|
|
|
|
|
fail:
|
|
fail:
|
|
|
- /* FIXME: cleanup properly. */
|
|
|
|
|
- talloc_free(p);
|
|
|
|
|
|
|
+ talloc_free(atp);
|
|
|
return NULL;
|
|
return NULL;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/* Say something to our parent (async). */
|
|
/* Say something to our parent (async). */
|
|
|
-void at_tell_parent(struct at_pool *pool, const void *status)
|
|
|
|
|
|
|
+void at_tell_parent(struct at_pool *atp, const void *status)
|
|
|
{
|
|
{
|
|
|
- if (pool->parent_wfd == -1)
|
|
|
|
|
|
|
+ if (atp->p->parent_wfd == -1)
|
|
|
errx(1, "This process is not an antithread of this pool");
|
|
errx(1, "This process is not an antithread of this pool");
|
|
|
|
|
|
|
|
- if (write(pool->parent_wfd, &status, sizeof(status)) != sizeof(status))
|
|
|
|
|
|
|
+ if (write(atp->p->parent_wfd, &status, sizeof(status))!=sizeof(status))
|
|
|
err(1, "Failure writing to parent");
|
|
err(1, "Failure writing to parent");
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/* What's the parent saying? Blocks if fd not ready. */
|
|
/* What's the parent saying? Blocks if fd not ready. */
|
|
|
-void *at_read_parent(struct at_pool *pool)
|
|
|
|
|
|
|
+void *at_read_parent(struct at_pool *atp)
|
|
|
{
|
|
{
|
|
|
void *ret;
|
|
void *ret;
|
|
|
|
|
|
|
|
- if (pool->parent_rfd == -1)
|
|
|
|
|
|
|
+ if (atp->p->parent_rfd == -1)
|
|
|
errx(1, "This process is not an antithread of this pool");
|
|
errx(1, "This process is not an antithread of this pool");
|
|
|
|
|
|
|
|
- switch (read(pool->parent_rfd, &ret, sizeof(ret))) {
|
|
|
|
|
|
|
+ switch (read(atp->p->parent_rfd, &ret, sizeof(ret))) {
|
|
|
case -1:
|
|
case -1:
|
|
|
err(1, "Reading from parent");
|
|
err(1, "Reading from parent");
|
|
|
case 0:
|
|
case 0:
|
|
@@ -429,18 +497,18 @@ void *at_read_parent(struct at_pool *pool)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/* The fd to poll on */
|
|
/* The fd to poll on */
|
|
|
-int at_parent_fd(struct at_pool *pool)
|
|
|
|
|
|
|
+int at_parent_fd(struct at_pool *atp)
|
|
|
{
|
|
{
|
|
|
- if (pool->parent_rfd == -1)
|
|
|
|
|
|
|
+ if (atp->p->parent_rfd == -1)
|
|
|
errx(1, "This process is not an antithread of this pool");
|
|
errx(1, "This process is not an antithread of this pool");
|
|
|
|
|
|
|
|
- return pool->parent_rfd;
|
|
|
|
|
|
|
+ return atp->p->parent_rfd;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/* FIXME: Futexme. */
|
|
/* FIXME: Futexme. */
|
|
|
void at_lock(void *obj)
|
|
void at_lock(void *obj)
|
|
|
{
|
|
{
|
|
|
- struct at_pool *p = talloc_find_parent_bytype(obj, struct at_pool);
|
|
|
|
|
|
|
+ struct at_pool *atp = talloc_find_parent_bytype(obj, struct at_pool);
|
|
|
#if 0
|
|
#if 0
|
|
|
unsigned int *l;
|
|
unsigned int *l;
|
|
|
|
|
|
|
@@ -448,7 +516,7 @@ void at_lock(void *obj)
|
|
|
l = talloc_lock_ptr(obj);
|
|
l = talloc_lock_ptr(obj);
|
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
|
- lock(p->fd, (char *)obj - (char *)p->pool);
|
|
|
|
|
|
|
+ lock(atp->p->fd, (char *)obj - (char *)atp->p->pool);
|
|
|
|
|
|
|
|
#if 0
|
|
#if 0
|
|
|
if (*l)
|
|
if (*l)
|
|
@@ -459,7 +527,7 @@ void at_lock(void *obj)
|
|
|
|
|
|
|
|
void at_unlock(void *obj)
|
|
void at_unlock(void *obj)
|
|
|
{
|
|
{
|
|
|
- struct at_pool *p = talloc_find_parent_bytype(obj, struct at_pool);
|
|
|
|
|
|
|
+ struct at_pool *atp = talloc_find_parent_bytype(obj, struct at_pool);
|
|
|
#if 0
|
|
#if 0
|
|
|
unsigned int *l;
|
|
unsigned int *l;
|
|
|
|
|
|
|
@@ -468,15 +536,15 @@ void at_unlock(void *obj)
|
|
|
errx(1, "Object %p was already unlocked", obj);
|
|
errx(1, "Object %p was already unlocked", obj);
|
|
|
*l = 0;
|
|
*l = 0;
|
|
|
#endif
|
|
#endif
|
|
|
- unlock(p->fd, (char *)obj - (char *)p->pool);
|
|
|
|
|
|
|
+ unlock(atp->p->fd, (char *)obj - (char *)atp->p->pool);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-void at_lock_all(struct at_pool *p)
|
|
|
|
|
|
|
+void at_lock_all(struct at_pool *atp)
|
|
|
{
|
|
{
|
|
|
- lock(p->fd, 0);
|
|
|
|
|
|
|
+ lock(atp->p->fd, 0);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-void at_unlock_all(struct at_pool *p)
|
|
|
|
|
|
|
+void at_unlock_all(struct at_pool *atp)
|
|
|
{
|
|
{
|
|
|
- unlock(p->fd, 0);
|
|
|
|
|
|
|
+ unlock(atp->p->fd, 0);
|
|
|
}
|
|
}
|