From c5d07df6abe657ff196266bbfbb376ca7db0968b Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 24 Mar 2014 10:39:56 +0000 Subject: [PATCH] pthreadpool: Allow multiple jobs to be received This can avoid syscalls when multiple jobs are finished simultaneously Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison --- source3/lib/asys/asys.c | 6 +++--- source3/lib/fncall.c | 2 +- source3/lib/pthreadpool/pthreadpool.c | 19 ++++++++++--------- source3/lib/pthreadpool/pthreadpool.h | 13 ++++++++----- source3/lib/pthreadpool/pthreadpool_sync.c | 26 +++++++++++++++++--------- source3/lib/pthreadpool/tests.c | 8 ++++---- source3/modules/vfs_aio_pthread.c | 4 ++-- source3/torture/bench_pthreadpool.c | 8 ++++---- 8 files changed, 49 insertions(+), 37 deletions(-) diff --git a/source3/lib/asys/asys.c b/source3/lib/asys/asys.c index 9937d2482d5..1fd7700f9bf 100644 --- a/source3/lib/asys/asys.c +++ b/source3/lib/asys/asys.c @@ -295,9 +295,9 @@ int asys_result(struct asys_context *ctx, ssize_t *pret, int *perrno, struct asys_job *job; int ret, jobid; - ret = pthreadpool_finished_job(ctx->pool, &jobid); - if (ret != 0) { - return ret; + ret = pthreadpool_finished_jobs(ctx->pool, &jobid, 1); + if (ret < 0) { + return -ret; } if ((jobid < 0) || (jobid >= ctx->num_jobs)) { return EIO; diff --git a/source3/lib/fncall.c b/source3/lib/fncall.c index 7f728ba0158..88304d6961c 100644 --- a/source3/lib/fncall.c +++ b/source3/lib/fncall.c @@ -287,7 +287,7 @@ static void fncall_handler(struct tevent_context *ev, struct tevent_fd *fde, int i, num_pending; int job_id; - if (pthreadpool_finished_job(ctx->pool, &job_id) != 0) { + if (pthreadpool_finished_jobs(ctx->pool, &job_id, 1) < 0) { return; } diff --git a/source3/lib/pthreadpool/pthreadpool.c b/source3/lib/pthreadpool/pthreadpool.c index d51e8083601..4436ab3289f 100644 --- a/source3/lib/pthreadpool/pthreadpool.c +++ b/source3/lib/pthreadpool/pthreadpool.c @@ -288,25 +288,26 @@ static void pthreadpool_join_children(struct pthreadpool *pool) * Fetch a finished job number from the signal pipe */ -int pthreadpool_finished_job(struct pthreadpool *pool, int *jobid) +int pthreadpool_finished_jobs(struct pthreadpool *pool, int *jobids, + unsigned num_jobids) { - int ret_jobid; - ssize_t nread; + ssize_t to_read, nread; nread = -1; errno = EINTR; + to_read = sizeof(int) * num_jobids; + while ((nread == -1) && (errno == EINTR)) { - nread = read(pool->sig_pipe[0], &ret_jobid, sizeof(int)); + nread = read(pool->sig_pipe[0], jobids, to_read); } if (nread == -1) { - return errno; + return -errno; } - if (nread != sizeof(int)) { - return EINVAL; + if ((nread % sizeof(int)) != 0) { + return -EINVAL; } - *jobid = ret_jobid; - return 0; + return nread / sizeof(int); } /* diff --git a/source3/lib/pthreadpool/pthreadpool.h b/source3/lib/pthreadpool/pthreadpool.h index fac2d254249..adb825a528a 100644 --- a/source3/lib/pthreadpool/pthreadpool.h +++ b/source3/lib/pthreadpool/pthreadpool.h @@ -61,7 +61,7 @@ int pthreadpool_destroy(struct pthreadpool *pool); * * This adds a job to a pthreadpool. The job can be identified by * job_id. This integer will be returned from - * pthreadpool_finished_job() then the job is completed. + * pthreadpool_finished_jobs() then the job is completed. * * @param[in] pool The pool to run the job on * @param[in] job_id A custom identifier @@ -84,15 +84,18 @@ int pthreadpool_add_job(struct pthreadpool *pool, int job_id, int pthreadpool_signal_fd(struct pthreadpool *pool); /** - * @brief Get the job_id of a finished job + * @brief Get the job_ids of finished jobs * * This blocks until a job has finished unless the fd returned by * pthreadpool_signal_fd() is readable. * * @param[in] pool The pool to query for finished jobs - * @param[out] pjobid The job_id of the finished job - * @return success: 0, failure: errno + * @param[out] jobids The job_ids of the finished job + * @param[int] num_jobids The job_ids array size + * @return success: >=0, number of finished jobs + * failure: -errno */ -int pthreadpool_finished_job(struct pthreadpool *pool, int *jobid); +int pthreadpool_finished_jobs(struct pthreadpool *pool, int *jobids, + unsigned num_jobids); #endif diff --git a/source3/lib/pthreadpool/pthreadpool_sync.c b/source3/lib/pthreadpool/pthreadpool_sync.c index 0c2d12fef30..5f06cae2f8c 100644 --- a/source3/lib/pthreadpool/pthreadpool_sync.c +++ b/source3/lib/pthreadpool/pthreadpool_sync.c @@ -133,27 +133,35 @@ int pthreadpool_add_job(struct pthreadpool *pool, int job_id, } -int pthreadpool_finished_job(struct pthreadpool *pool, int *jobid) +int pthreadpool_finished_jobs(struct pthreadpool *pool, int *jobids, + unsigned num_jobids) { - int ret_jobid; - ssize_t nread; + ssize_t to_read, nread; + int ret; nread = -1; errno = EINTR; + to_read = sizeof(int) * num_jobids; + while ((nread == -1) && (errno == EINTR)) { - nread = read(pool->sig_pipe[0], &ret_jobid, sizeof(int)); + nread = read(pool->sig_pipe[0], jobids, to_read); } if (nread == -1) { - return errno; + return -errno; } - if (nread != sizeof(int)) { - return EINVAL; + if ((nread % sizeof(int)) != 0) { + return -EINVAL; } - *jobid = ret_jobid; pool->pipe_busy = 0; - return pthreadpool_write_to_pipe(pool); + + ret = pthreadpool_write_to_pipe(pool); + if (ret != 0) { + return -ret; + } + + return nread / sizeof(int); } int pthreadpool_destroy(struct pthreadpool *pool) diff --git a/source3/lib/pthreadpool/tests.c b/source3/lib/pthreadpool/tests.c index 170cedf07f7..847471297fa 100644 --- a/source3/lib/pthreadpool/tests.c +++ b/source3/lib/pthreadpool/tests.c @@ -71,8 +71,8 @@ static int test_jobs(int num_threads, int num_jobs) for (i=0; i= num_jobs)) { + ret = pthreadpool_finished_jobs(p, &jobid, 1); + if ((ret != 1) || (jobid >= num_jobs)) { fprintf(stderr, "invalid job number %d\n", jobid); return -1; } @@ -284,8 +284,8 @@ static int test_threaded_addjob(int num_pools, int num_threads, int poolsize, continue; } - ret = pthreadpool_finished_job(pools[j], &jobid); - if ((ret != 0) || (jobid >= num_jobs * num_threads)) { + ret = pthreadpool_finished_jobs(pools[j], &jobid, 1); + if ((ret != 1) || (jobid >= num_jobs * num_threads)) { fprintf(stderr, "invalid job number %d\n", jobid); return -1; diff --git a/source3/modules/vfs_aio_pthread.c b/source3/modules/vfs_aio_pthread.c index f7756b946c9..de114d1292e 100644 --- a/source3/modules/vfs_aio_pthread.c +++ b/source3/modules/vfs_aio_pthread.c @@ -166,8 +166,8 @@ static void aio_open_handle_completion(struct tevent_context *event_ctx, return; } - ret = pthreadpool_finished_job(open_pool, &jobid); - if (ret) { + ret = pthreadpool_finished_jobs(open_pool, &jobid, 1); + if (ret != 1) { smb_panic("aio_open_handle_completion"); /* notreached. */ return; diff --git a/source3/torture/bench_pthreadpool.c b/source3/torture/bench_pthreadpool.c index ee0d2036b64..247063d9694 100644 --- a/source3/torture/bench_pthreadpool.c +++ b/source3/torture/bench_pthreadpool.c @@ -50,15 +50,15 @@ bool run_bench_pthreadpool(int dummy) strerror(ret)); break; } - ret = pthreadpool_finished_job(pool, &jobid); - if (ret != 0) { + ret = pthreadpool_finished_jobs(pool, &jobid, 1); + if (ret < 0) { d_fprintf(stderr, "pthreadpool_finished_job failed: %s\n", - strerror(ret)); + strerror(-ret)); break; } } pthreadpool_destroy(pool); - return (ret == 0); + return (ret == 1); } -- 2.11.4.GIT