summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorylavic <ylavic@13f79535-47bb-0310-9956-ffa450edef68>2022-07-21 11:12:34 +0000
committerylavic <ylavic@13f79535-47bb-0310-9956-ffa450edef68>2022-07-21 11:12:34 +0000
commitc6b9ce6906fe186b746690e6ec6eaf54c019b9ad (patch)
tree98e92be675db484d0fd187fc81067b687a03f670
parentd6aa35955c15b2716ef42bcc71998105c3b64be4 (diff)
downloadlibapr-c6b9ce6906fe186b746690e6ec6eaf54c019b9ad.tar.gz
apr_thread: Provide apr_threadattr_max_free_set().
When creating a thread, this allows to specify the "max_free" of its pool allocator (i.e. apr_allocator_max_free_set), so that one can create thread local subpools and have their memory usage regulated on cleanup/destroy. One could achieve that already with: apr_allocator_max_free_set(apr_thread_pool_get(thread), max_free); in the thread startup function, but it's more convenient, simpler and race free to handle that in the thread attribute itself at creation time. Merge r1902715 from trunk. git-svn-id: https://svn.apache.org/repos/asf/apr/apr/branches/1.8.x@1902908 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--include/apr_thread_proc.h9
-rw-r--r--include/arch/beos/apr_arch_threadproc.h1
-rw-r--r--include/arch/netware/apr_arch_threadproc.h1
-rw-r--r--include/arch/os2/apr_arch_threadproc.h1
-rw-r--r--include/arch/unix/apr_arch_threadproc.h1
-rw-r--r--include/arch/win32/apr_arch_threadproc.h1
-rw-r--r--threadproc/beos/thread.c22
-rw-r--r--threadproc/netware/thread.c22
-rw-r--r--threadproc/os2/thread.c22
-rw-r--r--threadproc/unix/thread.c22
-rw-r--r--threadproc/win32/thread.c22
11 files changed, 74 insertions, 50 deletions
diff --git a/include/apr_thread_proc.h b/include/apr_thread_proc.h
index fe5e3206e..d285861a4 100644
--- a/include/apr_thread_proc.h
+++ b/include/apr_thread_proc.h
@@ -278,6 +278,15 @@ APR_DECLARE(apr_status_t) apr_threadattr_guardsize_set(apr_threadattr_t *attr,
apr_size_t guardsize);
/**
+ * Set the threshold at which the thread pool allocator should start
+ * giving blocks back to the system.
+ * @param attr The threadattr to affect
+ * @param on Non-zero if detached threads should be created.
+ */
+APR_DECLARE(apr_status_t) apr_threadattr_max_free_set(apr_threadattr_t *attr,
+ apr_size_t size);
+
+/**
* Create a new thread of execution
* @param new_thread The newly created thread handle.
* @param attr The threadattr to use to determine how to create the thread
diff --git a/include/arch/beos/apr_arch_threadproc.h b/include/arch/beos/apr_arch_threadproc.h
index b7db0a300..46a869eee 100644
--- a/include/arch/beos/apr_arch_threadproc.h
+++ b/include/arch/beos/apr_arch_threadproc.h
@@ -53,6 +53,7 @@ struct apr_threadattr_t {
int32 attr;
int detached;
int joinable;
+ apr_size_t max_free;
};
struct apr_threadkey_t {
diff --git a/include/arch/netware/apr_arch_threadproc.h b/include/arch/netware/apr_arch_threadproc.h
index ce217aaba..d726b34f7 100644
--- a/include/arch/netware/apr_arch_threadproc.h
+++ b/include/arch/netware/apr_arch_threadproc.h
@@ -44,6 +44,7 @@ struct apr_threadattr_t {
apr_size_t stack_size;
apr_int32_t detach;
char *thread_name;
+ apr_size_t max_free;
};
struct apr_threadkey_t {
diff --git a/include/arch/os2/apr_arch_threadproc.h b/include/arch/os2/apr_arch_threadproc.h
index c8017adbf..5e6b6a40d 100644
--- a/include/arch/os2/apr_arch_threadproc.h
+++ b/include/arch/os2/apr_arch_threadproc.h
@@ -29,6 +29,7 @@ struct apr_threadattr_t {
apr_pool_t *pool;
unsigned long attr;
apr_size_t stacksize;
+ apr_size_t max_free;
};
struct apr_thread_t {
diff --git a/include/arch/unix/apr_arch_threadproc.h b/include/arch/unix/apr_arch_threadproc.h
index adeb51c8a..c39aeaa8f 100644
--- a/include/arch/unix/apr_arch_threadproc.h
+++ b/include/arch/unix/apr_arch_threadproc.h
@@ -65,6 +65,7 @@ struct apr_thread_t {
struct apr_threadattr_t {
apr_pool_t *pool;
pthread_attr_t attr;
+ apr_size_t max_free;
};
struct apr_threadkey_t {
diff --git a/include/arch/win32/apr_arch_threadproc.h b/include/arch/win32/apr_arch_threadproc.h
index b39fdbbea..ea6556472 100644
--- a/include/arch/win32/apr_arch_threadproc.h
+++ b/include/arch/win32/apr_arch_threadproc.h
@@ -38,6 +38,7 @@ struct apr_threadattr_t {
apr_pool_t *pool;
apr_int32_t detach;
apr_size_t stacksize;
+ apr_size_t max_free;
};
struct apr_threadkey_t {
diff --git a/threadproc/beos/thread.c b/threadproc/beos/thread.c
index 39a5e366c..0ca7131da 100644
--- a/threadproc/beos/thread.c
+++ b/threadproc/beos/thread.c
@@ -62,6 +62,13 @@ APR_DECLARE(apr_status_t) apr_threadattr_guardsize_set(apr_threadattr_t *attr,
return APR_ENOTIMPL;
}
+APR_DECLARE(apr_status_t) apr_threadattr_max_free_set(apr_threadattr_t *attr,
+ apr_size_t size)
+{
+ attr->max_free = size;
+ return APR_SUCCESS;
+}
+
#if APR_HAS_THREAD_LOCAL
static APR_THREAD_LOCAL apr_thread_t *current_thread = NULL;
#endif
@@ -90,27 +97,22 @@ static apr_status_t alloc_thread(apr_thread_t **new,
{
apr_status_t stat;
apr_abortfunc_t abort_fn = apr_pool_abort_get(pool);
- apr_allocator_t *allocator;
apr_pool_t *p;
/* The thread can be detached anytime (from the creation or later with
* apr_thread_detach), so it needs its own pool and allocator to not
* depend on a parent pool which could be destroyed before the thread
* exits. The allocator needs no mutex obviously since the pool should
- * not be used nor create children pools outside the thread.
+ * not be used nor create children pools outside the thread. Passing
+ * NULL allocator will create one like that.
*/
- stat = apr_allocator_create(&allocator);
+ stat = apr_pool_create_unmanaged_ex(&p, abort_fn, NULL);
if (stat != APR_SUCCESS) {
- if (abort_fn)
- abort_fn(stat);
return stat;
}
- stat = apr_pool_create_unmanaged_ex(&p, abort_fn, allocator);
- if (stat != APR_SUCCESS) {
- apr_allocator_destroy(allocator);
- return stat;
+ if (attr && attr->max_free) {
+ apr_allocator_max_free_set(apr_pool_allocator_get(p), attr->max_free);
}
- apr_allocator_owner_set(allocator, p);
(*new) = (apr_thread_t *)apr_pcalloc(p, sizeof(apr_thread_t));
if ((*new) == NULL) {
diff --git a/threadproc/netware/thread.c b/threadproc/netware/thread.c
index fd74a9685..0672d4af6 100644
--- a/threadproc/netware/thread.c
+++ b/threadproc/netware/thread.c
@@ -64,6 +64,13 @@ APR_DECLARE(apr_status_t) apr_threadattr_guardsize_set(apr_threadattr_t *attr,
return APR_ENOTIMPL;
}
+APR_DECLARE(apr_status_t) apr_threadattr_max_free_set(apr_threadattr_t *attr,
+ apr_size_t size)
+{
+ attr->max_free = size;
+ return APR_SUCCESS;
+}
+
#if APR_HAS_THREAD_LOCAL
static APR_THREAD_LOCAL apr_thread_t *current_thread = NULL;
#endif
@@ -92,27 +99,22 @@ static apr_status_t alloc_thread(apr_thread_t **new,
{
apr_status_t stat;
apr_abortfunc_t abort_fn = apr_pool_abort_get(pool);
- apr_allocator_t *allocator;
apr_pool_t *p;
/* The thread can be detached anytime (from the creation or later with
* apr_thread_detach), so it needs its own pool and allocator to not
* depend on a parent pool which could be destroyed before the thread
* exits. The allocator needs no mutex obviously since the pool should
- * not be used nor create children pools outside the thread.
+ * not be used nor create children pools outside the thread. Passing
+ * NULL allocator will create one like that.
*/
- stat = apr_allocator_create(&allocator);
+ stat = apr_pool_create_unmanaged_ex(&p, abort_fn, NULL);
if (stat != APR_SUCCESS) {
- if (abort_fn)
- abort_fn(stat);
return stat;
}
- stat = apr_pool_create_unmanaged_ex(&p, abort_fn, allocator);
- if (stat != APR_SUCCESS) {
- apr_allocator_destroy(allocator);
- return stat;
+ if (attr && attr->max_free) {
+ apr_allocator_max_free_set(apr_pool_allocator_get(p), attr->max_free);
}
- apr_allocator_owner_set(allocator, p);
(*new) = (apr_thread_t *)apr_pcalloc(p, sizeof(apr_thread_t));
if ((*new) == NULL) {
diff --git a/threadproc/os2/thread.c b/threadproc/os2/thread.c
index 79b24f535..1f693950d 100644
--- a/threadproc/os2/thread.c
+++ b/threadproc/os2/thread.c
@@ -68,6 +68,13 @@ APR_DECLARE(apr_status_t) apr_threadattr_guardsize_set(apr_threadattr_t *attr,
return APR_ENOTIMPL;
}
+APR_DECLARE(apr_status_t) apr_threadattr_max_free_set(apr_threadattr_t *attr,
+ apr_size_t size)
+{
+ attr->max_free = size;
+ return APR_SUCCESS;
+}
+
#if APR_HAS_THREAD_LOCAL
static APR_THREAD_LOCAL apr_thread_t *current_thread = NULL;
#endif
@@ -94,27 +101,22 @@ static apr_status_t alloc_thread(apr_thread_t **new,
{
apr_status_t stat;
apr_abortfunc_t abort_fn = apr_pool_abort_get(pool);
- apr_allocator_t *allocator;
apr_pool_t *p;
/* The thread can be detached anytime (from the creation or later with
* apr_thread_detach), so it needs its own pool and allocator to not
* depend on a parent pool which could be destroyed before the thread
* exits. The allocator needs no mutex obviously since the pool should
- * not be used nor create children pools outside the thread.
+ * not be used nor create children pools outside the thread. Passing
+ * NULL allocator will create one like that.
*/
- stat = apr_allocator_create(&allocator);
+ stat = apr_pool_create_unmanaged_ex(&p, abort_fn, NULL);
if (stat != APR_SUCCESS) {
- if (abort_fn)
- abort_fn(stat);
return stat;
}
- stat = apr_pool_create_unmanaged_ex(&p, abort_fn, allocator);
- if (stat != APR_SUCCESS) {
- apr_allocator_destroy(allocator);
- return stat;
+ if (attr && attr->max_free) {
+ apr_allocator_max_free_set(apr_pool_allocator_get(p), attr->max_free);
}
- apr_allocator_owner_set(allocator, p);
(*new) = (apr_thread_t *)apr_pcalloc(p, sizeof(apr_thread_t));
if ((*new) == NULL) {
diff --git a/threadproc/unix/thread.c b/threadproc/unix/thread.c
index d84d5ef0d..5ec219e23 100644
--- a/threadproc/unix/thread.c
+++ b/threadproc/unix/thread.c
@@ -136,6 +136,13 @@ APR_DECLARE(apr_status_t) apr_threadattr_guardsize_set(apr_threadattr_t *attr,
#endif
}
+APR_DECLARE(apr_status_t) apr_threadattr_max_free_set(apr_threadattr_t *attr,
+ apr_size_t size)
+{
+ attr->max_free = size;
+ return APR_SUCCESS;
+}
+
#if APR_HAS_THREAD_LOCAL
static APR_THREAD_LOCAL apr_thread_t *current_thread = NULL;
#endif
@@ -164,27 +171,22 @@ static apr_status_t alloc_thread(apr_thread_t **new,
{
apr_status_t stat;
apr_abortfunc_t abort_fn = apr_pool_abort_get(pool);
- apr_allocator_t *allocator;
apr_pool_t *p;
/* The thread can be detached anytime (from the creation or later with
* apr_thread_detach), so it needs its own pool and allocator to not
* depend on a parent pool which could be destroyed before the thread
* exits. The allocator needs no mutex obviously since the pool should
- * not be used nor create children pools outside the thread.
+ * not be used nor create children pools outside the thread. Passing
+ * NULL allocator will create one like that.
*/
- stat = apr_allocator_create(&allocator);
+ stat = apr_pool_create_unmanaged_ex(&p, abort_fn, NULL);
if (stat != APR_SUCCESS) {
- if (abort_fn)
- abort_fn(stat);
return stat;
}
- stat = apr_pool_create_unmanaged_ex(&p, abort_fn, allocator);
- if (stat != APR_SUCCESS) {
- apr_allocator_destroy(allocator);
- return stat;
+ if (attr && attr->max_free) {
+ apr_allocator_max_free_set(apr_pool_allocator_get(p), attr->max_free);
}
- apr_allocator_owner_set(allocator, p);
(*new) = (apr_thread_t *)apr_pcalloc(p, sizeof(apr_thread_t));
if ((*new) == NULL) {
diff --git a/threadproc/win32/thread.c b/threadproc/win32/thread.c
index 19ba008aa..04b08b107 100644
--- a/threadproc/win32/thread.c
+++ b/threadproc/win32/thread.c
@@ -72,6 +72,13 @@ APR_DECLARE(apr_status_t) apr_threadattr_guardsize_set(apr_threadattr_t *attr,
return APR_ENOTIMPL;
}
+APR_DECLARE(apr_status_t) apr_threadattr_max_free_set(apr_threadattr_t *attr,
+ apr_size_t size)
+{
+ attr->max_free = size;
+ return APR_SUCCESS;
+}
+
#if APR_HAS_THREAD_LOCAL
static APR_THREAD_LOCAL apr_thread_t *current_thread = NULL;
#endif
@@ -101,27 +108,22 @@ static apr_status_t alloc_thread(apr_thread_t **new,
{
apr_status_t stat;
apr_abortfunc_t abort_fn = apr_pool_abort_get(pool);
- apr_allocator_t *allocator;
apr_pool_t *p;
/* The thread can be detached anytime (from the creation or later with
* apr_thread_detach), so it needs its own pool and allocator to not
* depend on a parent pool which could be destroyed before the thread
* exits. The allocator needs no mutex obviously since the pool should
- * not be used nor create children pools outside the thread.
+ * not be used nor create children pools outside the thread. Passing
+ * NULL allocator will create one like that.
*/
- stat = apr_allocator_create(&allocator);
+ stat = apr_pool_create_unmanaged_ex(&p, abort_fn, NULL);
if (stat != APR_SUCCESS) {
- if (abort_fn)
- abort_fn(stat);
return stat;
}
- stat = apr_pool_create_unmanaged_ex(&p, abort_fn, allocator);
- if (stat != APR_SUCCESS) {
- apr_allocator_destroy(allocator);
- return stat;
+ if (attr && attr->max_free) {
+ apr_allocator_max_free_set(apr_pool_allocator_get(p), attr->max_free);
}
- apr_allocator_owner_set(allocator, p);
(*new) = (apr_thread_t *)apr_pcalloc(p, sizeof(apr_thread_t));
if ((*new) == NULL) {