diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 06:23:09 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 06:23:09 +0000 |
commit | 30d479c28c831a0d4f1fdb54a9e346b0fc176be1 (patch) | |
tree | aa35d7414ce9f1326abf6f723f6dfa5b0aa08b1d /threadproc/netware | |
parent | Initial commit. (diff) | |
download | apr-30d479c28c831a0d4f1fdb54a9e346b0fc176be1.tar.xz apr-30d479c28c831a0d4f1fdb54a9e346b0fc176be1.zip |
Adding upstream version 1.7.2.upstream/1.7.2
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | threadproc/netware/proc.c | 515 | ||||
-rw-r--r-- | threadproc/netware/procsup.c | 102 | ||||
-rw-r--r-- | threadproc/netware/signals.c | 81 | ||||
-rw-r--r-- | threadproc/netware/thread.c | 254 | ||||
-rw-r--r-- | threadproc/netware/threadpriv.c | 102 |
5 files changed, 1054 insertions, 0 deletions
diff --git a/threadproc/netware/proc.c b/threadproc/netware/proc.c new file mode 100644 index 0000000..e5306f9 --- /dev/null +++ b/threadproc/netware/proc.c @@ -0,0 +1,515 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_arch_threadproc.h" +#include "apr_arch_file_io.h" +#include "apr_strings.h" +#include "apr_portable.h" + +#include <proc.h> + +/* Heavy on no'ops, here's what we want to pass if there is APR_NO_FILE + * requested for a specific child handle; + */ +static apr_file_t no_file = { NULL, -1, }; + +static apr_status_t apr_netware_proc_cleanup(void *theproc) +{ + apr_proc_t *proc = theproc; + int exit_int; + int waitpid_options = WUNTRACED | WNOHANG; + + if (proc->pid > 0) { + waitpid(proc->pid, &exit_int, waitpid_options); + } + +/* NXVmDestroy(proc->pid); */ + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_procattr_create(apr_procattr_t **new,apr_pool_t *pool) +{ + (*new) = (apr_procattr_t *)apr_pcalloc(pool, sizeof(apr_procattr_t)); + + if ((*new) == NULL) { + return APR_ENOMEM; + } + (*new)->pool = pool; + (*new)->cmdtype = APR_PROGRAM; + /* Default to a current path since NetWare doesn't handle it very well */ + apr_filepath_get(&((*new)->currdir), APR_FILEPATH_NATIVE, pool); + (*new)->detached = 1; + return APR_SUCCESS; + +} + +APR_DECLARE(apr_status_t) apr_procattr_io_set(apr_procattr_t *attr, + apr_int32_t in, + apr_int32_t out, + apr_int32_t err) +{ + apr_status_t rv; + + if ((in != APR_NO_PIPE) && (in != APR_NO_FILE)) { + /* APR_CHILD_BLOCK maps to APR_WRITE_BLOCK, while + * APR_PARENT_BLOCK maps to APR_READ_BLOCK, so transpose + * the CHILD/PARENT blocking flags for the stdin pipe. + * stdout/stderr map to the correct mode by default. + */ + if (in == APR_CHILD_BLOCK) + in = APR_READ_BLOCK; + else if (in == APR_PARENT_BLOCK) + in = APR_WRITE_BLOCK; + + if ((rv = apr_file_pipe_create_ex(&attr->child_in, &attr->parent_in, + in, attr->pool)) == APR_SUCCESS) + rv = apr_file_inherit_unset(attr->parent_in); + if (rv != APR_SUCCESS) + return rv; + } + else if (in == APR_NO_FILE) + attr->child_in = &no_file; + + if ((out != APR_NO_PIPE) && (out != APR_NO_FILE)) { + if ((rv = apr_file_pipe_create_ex(&attr->parent_out, &attr->child_out, + out, attr->pool)) == APR_SUCCESS) + rv = apr_file_inherit_unset(attr->parent_out); + if (rv != APR_SUCCESS) + return rv; + } + else if (out == APR_NO_FILE) + attr->child_out = &no_file; + + if ((err != APR_NO_PIPE) && (err != APR_NO_FILE)) { + if ((rv = apr_file_pipe_create_ex(&attr->parent_err, &attr->child_err, + err, attr->pool)) == APR_SUCCESS) + rv = apr_file_inherit_unset(attr->parent_err); + if (rv != APR_SUCCESS) + return rv; + } + else if (err == APR_NO_FILE) + attr->child_err = &no_file; + + return APR_SUCCESS; +} + + +APR_DECLARE(apr_status_t) apr_procattr_child_in_set(apr_procattr_t *attr, apr_file_t *child_in, + apr_file_t *parent_in) +{ + apr_status_t rv = APR_SUCCESS; + + if (attr->child_in == NULL && attr->parent_in == NULL + && child_in == NULL && parent_in == NULL) + if ((rv = apr_file_pipe_create(&attr->child_in, &attr->parent_in, + attr->pool)) == APR_SUCCESS) + rv = apr_file_inherit_unset(attr->parent_in); + + if (child_in != NULL && rv == APR_SUCCESS) { + if (attr->child_in && (attr->child_in->filedes != -1)) + rv = apr_file_dup2(attr->child_in, child_in, attr->pool); + else { + attr->child_in = NULL; + if ((rv = apr_file_dup(&attr->child_in, child_in, attr->pool)) + == APR_SUCCESS) + rv = apr_file_inherit_set(attr->child_in); + } + } + + if (parent_in != NULL && rv == APR_SUCCESS) { + rv = apr_file_dup(&attr->parent_in, parent_in, attr->pool); + } + + return rv; +} + + +APR_DECLARE(apr_status_t) apr_procattr_child_out_set(apr_procattr_t *attr, apr_file_t *child_out, + apr_file_t *parent_out) +{ + apr_status_t rv = APR_SUCCESS; + + if (attr->child_out == NULL && attr->parent_out == NULL + && child_out == NULL && parent_out == NULL) + if ((rv = apr_file_pipe_create(&attr->parent_out, &attr->child_out, + attr->pool)) == APR_SUCCESS) + rv = apr_file_inherit_unset(attr->parent_out); + + if (child_out != NULL && rv == APR_SUCCESS) { + if (attr->child_out && (attr->child_out->filedes != -1)) + rv = apr_file_dup2(attr->child_out, child_out, attr->pool); + else { + attr->child_out = NULL; + if ((rv = apr_file_dup(&attr->child_out, child_out, attr->pool)) + == APR_SUCCESS) + rv = apr_file_inherit_set(attr->child_out); + } + } + + if (parent_out != NULL && rv == APR_SUCCESS) { + rv = apr_file_dup(&attr->parent_out, parent_out, attr->pool); + } + + return rv; +} + + +APR_DECLARE(apr_status_t) apr_procattr_child_err_set(apr_procattr_t *attr, apr_file_t *child_err, + apr_file_t *parent_err) +{ + apr_status_t rv = APR_SUCCESS; + + if (attr->child_err == NULL && attr->parent_err == NULL + && child_err == NULL && parent_err == NULL) + if ((rv = apr_file_pipe_create(&attr->parent_err, &attr->child_err, + attr->pool)) == APR_SUCCESS) + rv = apr_file_inherit_unset(attr->parent_err); + + if (child_err != NULL && rv == APR_SUCCESS) { + if (attr->child_err && (attr->child_err->filedes != -1)) + rv = apr_file_dup2(attr->child_err, child_err, attr->pool); + else { + attr->child_err = NULL; + if ((rv = apr_file_dup(&attr->child_err, child_err, attr->pool)) + == APR_SUCCESS) + rv = apr_file_inherit_set(attr->child_err); + } + } + + if (parent_err != NULL && rv == APR_SUCCESS) { + rv = apr_file_dup(&attr->parent_err, parent_err, attr->pool); + } + + return rv; +} + + +APR_DECLARE(apr_status_t) apr_procattr_dir_set(apr_procattr_t *attr, + const char *dir) +{ + return apr_filepath_merge(&attr->currdir, NULL, dir, + APR_FILEPATH_NATIVE, attr->pool); +} + +APR_DECLARE(apr_status_t) apr_procattr_cmdtype_set(apr_procattr_t *attr, + apr_cmdtype_e cmd) +{ + /* won't ever be called on this platform, so don't save the function pointer */ + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_procattr_detach_set(apr_procattr_t *attr, apr_int32_t detach) +{ + attr->detached = detach; + return APR_SUCCESS; +} + +#if APR_HAS_FORK +APR_DECLARE(apr_status_t) apr_proc_fork(apr_proc_t *proc, apr_pool_t *pool) +{ + int pid; + + if ((pid = fork()) < 0) { + return errno; + } + else if (pid == 0) { + proc->pid = pid; + proc->in = NULL; + proc->out = NULL; + proc->err = NULL; + return APR_INCHILD; + } + proc->pid = pid; + proc->in = NULL; + proc->out = NULL; + proc->err = NULL; + return APR_INPARENT; +} +#endif + +static apr_status_t limit_proc(apr_procattr_t *attr) +{ +#if APR_HAVE_STRUCT_RLIMIT && APR_HAVE_SETRLIMIT +#ifdef RLIMIT_CPU + if (attr->limit_cpu != NULL) { + if ((setrlimit(RLIMIT_CPU, attr->limit_cpu)) != 0) { + return errno; + } + } +#endif +#ifdef RLIMIT_NPROC + if (attr->limit_nproc != NULL) { + if ((setrlimit(RLIMIT_NPROC, attr->limit_nproc)) != 0) { + return errno; + } + } +#endif +#if defined(RLIMIT_AS) + if (attr->limit_mem != NULL) { + if ((setrlimit(RLIMIT_AS, attr->limit_mem)) != 0) { + return errno; + } + } +#elif defined(RLIMIT_DATA) + if (attr->limit_mem != NULL) { + if ((setrlimit(RLIMIT_DATA, attr->limit_mem)) != 0) { + return errno; + } + } +#elif defined(RLIMIT_VMEM) + if (attr->limit_mem != NULL) { + if ((setrlimit(RLIMIT_VMEM, attr->limit_mem)) != 0) { + return errno; + } + } +#endif +#else + /* + * Maybe make a note in error_log that setrlimit isn't supported?? + */ + +#endif + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_procattr_child_errfn_set(apr_procattr_t *attr, + apr_child_errfn_t *errfn) +{ + /* won't ever be called on this platform, so don't save the function pointer */ + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_procattr_error_check_set(apr_procattr_t *attr, + apr_int32_t chk) +{ + /* won't ever be used on this platform, so don't save the flag */ + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_procattr_addrspace_set(apr_procattr_t *attr, + apr_int32_t addrspace) +{ + attr->addrspace = addrspace; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_proc_create(apr_proc_t *newproc, + const char *progname, + const char * const *args, + const char * const *env, + apr_procattr_t *attr, + apr_pool_t *pool) +{ + wiring_t wire; + int addr_space; + + wire.infd = attr->child_in + ? (attr->child_in->filedes != -1 ? attr->child_in->filedes + : FD_UNUSED) + : fileno(stdin); + wire.outfd = attr->child_out + ? (attr->child_out->filedes != -1 ? attr->child_out->filedes + : FD_UNUSED) + : fileno(stdout); + wire.errfd = attr->child_err + ? (attr->child_err->filedes != -1 ? attr->child_err->filedes + : FD_UNUSED) + : fileno(stderr); + + newproc->in = attr->parent_in; + newproc->out = attr->parent_out; + newproc->err = attr->parent_err; + + /* attr->detached and PROC_DETACHED do not mean the same thing. attr->detached means + * start the NLM in a separate address space. PROC_DETACHED means don't wait for the + * NLM to unload by calling wait() or waitpid(), just clean up */ + addr_space = PROC_LOAD_SILENT | (attr->addrspace ? 0 : PROC_CURRENT_SPACE); + addr_space |= (attr->detached ? PROC_DETACHED : 0); + + if (attr->currdir) { + char *fullpath = NULL; + apr_status_t rv; + + if ((rv = apr_filepath_merge(&fullpath, attr->currdir, progname, + APR_FILEPATH_NATIVE, pool)) != APR_SUCCESS) { + return rv; + } + progname = fullpath; + } + + if ((newproc->pid = procve(progname, addr_space, (const char**)env, &wire, + NULL, NULL, 0, NULL, (const char **)args)) == -1) { + return errno; + } + + if (attr->child_in && (attr->child_in->filedes != -1)) { + apr_pool_cleanup_kill(apr_file_pool_get(attr->child_in), + attr->child_in, apr_unix_file_cleanup); + apr_file_close(attr->child_in); + } + if (attr->child_out && (attr->child_out->filedes != -1)) { + apr_pool_cleanup_kill(apr_file_pool_get(attr->child_out), + attr->child_out, apr_unix_file_cleanup); + apr_file_close(attr->child_out); + } + if (attr->child_err && (attr->child_err->filedes != -1)) { + apr_pool_cleanup_kill(apr_file_pool_get(attr->child_err), + attr->child_err, apr_unix_file_cleanup); + apr_file_close(attr->child_err); + } + + apr_pool_cleanup_register(pool, (void *)newproc, apr_netware_proc_cleanup, + apr_pool_cleanup_null); + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_proc_wait_all_procs(apr_proc_t *proc, + int *exitcode, + apr_exit_why_e *exitwhy, + apr_wait_how_e waithow, + apr_pool_t *p) +{ + proc->pid = -1; + return apr_proc_wait(proc, exitcode, exitwhy, waithow); +} + +APR_DECLARE(apr_status_t) apr_proc_wait(apr_proc_t *proc, + int *exitcode, apr_exit_why_e *exitwhy, + apr_wait_how_e waithow) +{ + pid_t pstatus; + int waitpid_options = WUNTRACED; + int exit_int; + int ignore; + apr_exit_why_e ignorewhy; + + if (exitcode == NULL) { + exitcode = &ignore; + } + + if (exitwhy == NULL) { + exitwhy = &ignorewhy; + } + + if (waithow != APR_WAIT) { + waitpid_options |= WNOHANG; + } + + /* If the pid is 0 then the process was started detached. There + is no need to wait since there is nothing to wait for on a + detached process. Starting a process as non-detached and + then calling wait or waitpid could cause the thread to hang. + The reason for this is because NetWare does not have a way + to kill or even signal a process to be killed. Starting + all processes as detached avoids the possibility of a + thread hanging. */ + if (proc->pid == 0) { + *exitwhy = APR_PROC_EXIT; + *exitcode = 0; + return APR_CHILD_DONE; + } + + if ((pstatus = waitpid(proc->pid, &exit_int, waitpid_options)) > 0) { + proc->pid = pstatus; + + if (WIFEXITED(exit_int)) { + *exitwhy = APR_PROC_EXIT; + *exitcode = WEXITSTATUS(exit_int); + } + else if (WIFSIGNALED(exit_int)) { + *exitwhy = APR_PROC_SIGNAL; + *exitcode = WIFTERMSIG(exit_int); + } + else { + /* unexpected condition */ + return APR_EGENERAL; + } + + return APR_CHILD_DONE; + } + else if (pstatus == 0) { + return APR_CHILD_NOTDONE; + } + + return errno; +} + +#if APR_HAVE_STRUCT_RLIMIT +APR_DECLARE(apr_status_t) apr_procattr_limit_set(apr_procattr_t *attr, + apr_int32_t what, + struct rlimit *limit) +{ + switch(what) { + case APR_LIMIT_CPU: +#ifdef RLIMIT_CPU + attr->limit_cpu = limit; + break; +#else + return APR_ENOTIMPL; +#endif + + case APR_LIMIT_MEM: +#if defined(RLIMIT_DATA) || defined(RLIMIT_VMEM) || defined(RLIMIT_AS) + attr->limit_mem = limit; + break; +#else + return APR_ENOTIMPL; +#endif + + case APR_LIMIT_NPROC: +#ifdef RLIMIT_NPROC + attr->limit_nproc = limit; + break; +#else + return APR_ENOTIMPL; +#endif + + case APR_LIMIT_NOFILE: +#ifdef RLIMIT_NOFILE + attr->limit_nofile = limit; + break; +#else + return APR_ENOTIMPL; +#endif + + } + return APR_SUCCESS; +} +#endif /* APR_HAVE_STRUCT_RLIMIT */ + +APR_DECLARE(apr_status_t) apr_procattr_user_set(apr_procattr_t *attr, + const char *username, + const char *password) +{ + /* Always return SUCCESS because NetWare threads don't run as a user */ + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_procattr_group_set(apr_procattr_t *attr, + const char *groupname) +{ + /* Always return SUCCESS because NetWare threads don't run within a group */ + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_procattr_perms_set_register(apr_procattr_t *attr, + apr_perms_setfn_t *perms_set_fn, + void *data, + apr_fileperms_t perms) +{ + return APR_ENOTIMPL; +} diff --git a/threadproc/netware/procsup.c b/threadproc/netware/procsup.c new file mode 100644 index 0000000..72fa1d9 --- /dev/null +++ b/threadproc/netware/procsup.c @@ -0,0 +1,102 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_arch_threadproc.h" + +apr_status_t apr_proc_detach(int daemonize) +{ +#if 0 + int x; + pid_t pgrp; + + chdir("/"); +#if !defined(MPE) && !defined(OS2) && !defined(TPF) && !defined(BEOS) +/* Don't detach for MPE because child processes can't survive the death of + the parent. */ + if ((x = fork()) > 0) + exit(0); + else if (x == -1) { + perror("fork"); + fprintf(stderr, "unable to fork new process\n"); + exit(1); /* we can't do anything here, so just exit. */ + } +/* RAISE_SIGSTOP(DETACH);*/ +#endif +#if APR_HAVE_SETSID + if ((pgrp = setsid()) == -1) { + return errno; + } +#elif defined(NEXT) || defined(NEWSOS) + if (setpgrp(0, getpid()) == -1 || (pgrp = getpgrp(0)) == -1) { + return errno; + } +#elif defined(OS2) || defined(TPF) + /* OS/2 don't support process group IDs */ + pgrp = getpid(); +#elif defined(MPE) + /* MPE uses negative pid for process group */ + pgrp = -getpid(); +#else + if ((pgrp = setpgid(0, 0)) == -1) { + return errno; + } +#endif + + /* close out the standard file descriptors */ + if (freopen("/dev/null", "r", stdin) == NULL) { + return errno; + /* continue anyhow -- note we can't close out descriptor 0 because we + * have nothing to replace it with, and if we didn't have a descriptor + * 0 the next file would be created with that value ... leading to + * havoc. + */ + } + if (freopen("/dev/null", "w", stdout) == NULL) { + return errno; + } + /* We are going to reopen this again in a little while to the error + * log file, but better to do it twice and suffer a small performance + * hit for consistancy than not reopen it here. + */ + if (freopen("/dev/null", "w", stderr) == NULL) { + return errno; + } +#endif + return APR_SUCCESS; +} + +#if 0 +#if (!HAVE_WAITPID) +/* From ikluft@amdahl.com + * this is not ideal but it works for SVR3 variants + * Modified by dwd@bell-labs.com to call wait3 instead of wait because + * apache started to use the WNOHANG option. + */ +int waitpid(pid_t pid, int *statusp, int options) +{ + int tmp_pid; + if (kill(pid, 0) == -1) { + errno = ECHILD; + return -1; + } + while (((tmp_pid = wait3(statusp, options, 0)) != pid) && + (tmp_pid != -1) && (tmp_pid != 0) && (pid != -1)) + ; + return tmp_pid; +} +#endif +#endif + diff --git a/threadproc/netware/signals.c b/threadproc/netware/signals.c new file mode 100644 index 0000000..c744da5 --- /dev/null +++ b/threadproc/netware/signals.c @@ -0,0 +1,81 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_arch_threadproc.h" +#include "apr_private.h" +#include "apr_pools.h" +#include "apr_signal.h" +#include "apr_strings.h" + +#include <assert.h> +#if APR_HAS_THREADS && APR_HAVE_PTHREAD_H +#include <pthread.h> +#endif + +APR_DECLARE(apr_status_t) apr_proc_kill(apr_proc_t *proc, int signum) +{ + return APR_ENOTIMPL; +} + + +void apr_signal_init(apr_pool_t *pglobal) +{ +} + +const char *apr_signal_description_get(int signum) +{ + switch (signum) + { + case SIGABRT: + return "Abort"; + case SIGFPE: + return "Arithmetic exception"; + case SIGILL: + return "Illegal instruction"; + case SIGINT: + return "Interrupt"; + case SIGSEGV: + return "Segmentation fault"; + case SIGTERM: + return "Terminated"; + case SIGPOLL: + return "Pollable event occurred"; + default: + return "unknown signal (not supported)"; + } +} + +static void *signal_thread_func(void *signal_handler) +{ + return NULL; +} + +#if (APR_HAVE_SIGWAIT || APR_HAVE_SIGSUSPEND) +APR_DECLARE(apr_status_t) apr_setup_signal_thread(void) +{ + return 0; +} +#endif /* (APR_HAVE_SIGWAIT || APR_HAVE_SIGSUSPEND) */ + +APR_DECLARE(apr_status_t) apr_signal_block(int signum) +{ + return APR_ENOTIMPL; +} + +APR_DECLARE(apr_status_t) apr_signal_unblock(int signum) +{ + return APR_ENOTIMPL; +} diff --git a/threadproc/netware/thread.c b/threadproc/netware/thread.c new file mode 100644 index 0000000..f983668 --- /dev/null +++ b/threadproc/netware/thread.c @@ -0,0 +1,254 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr.h" +#include "apr_portable.h" +#include "apr_strings.h" +#include "apr_arch_threadproc.h" + +static int thread_count = 0; + +apr_status_t apr_threadattr_create(apr_threadattr_t **new, + apr_pool_t *pool) +{ + (*new) = (apr_threadattr_t *)apr_palloc(pool, + sizeof(apr_threadattr_t)); + + if ((*new) == NULL) { + return APR_ENOMEM; + } + + (*new)->pool = pool; + (*new)->stack_size = APR_DEFAULT_STACK_SIZE; + (*new)->detach = 0; + (*new)->thread_name = NULL; + return APR_SUCCESS; +} + +apr_status_t apr_threadattr_detach_set(apr_threadattr_t *attr,apr_int32_t on) +{ + attr->detach = on; + return APR_SUCCESS; +} + +apr_status_t apr_threadattr_detach_get(apr_threadattr_t *attr) +{ + if (attr->detach == 1) + return APR_DETACH; + return APR_NOTDETACH; +} + +APR_DECLARE(apr_status_t) apr_threadattr_stacksize_set(apr_threadattr_t *attr, + apr_size_t stacksize) +{ + attr->stack_size = stacksize; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_threadattr_guardsize_set(apr_threadattr_t *attr, + apr_size_t size) +{ + return APR_ENOTIMPL; +} + +static void *dummy_worker(void *opaque) +{ + apr_thread_t *thd = (apr_thread_t *)opaque; + return thd->func(thd, thd->data); +} + +apr_status_t apr_thread_create(apr_thread_t **new, + apr_threadattr_t *attr, + apr_thread_start_t func, + void *data, + apr_pool_t *pool) +{ + apr_status_t stat; + unsigned long flags = NX_THR_BIND_CONTEXT; + char threadName[NX_MAX_OBJECT_NAME_LEN+1]; + size_t stack_size = APR_DEFAULT_STACK_SIZE; + + if (attr && attr->thread_name) { + strncpy (threadName, attr->thread_name, NX_MAX_OBJECT_NAME_LEN); + } + else { + sprintf(threadName, "APR_thread %04ld", ++thread_count); + } + + /* An original stack size of 0 will allow NXCreateThread() to + * assign a default system stack size. An original stack + * size of less than 0 will assign the APR default stack size. + * anything else will be taken as is. + */ + if (attr && (attr->stack_size >= 0)) { + stack_size = attr->stack_size; + } + + (*new) = (apr_thread_t *)apr_palloc(pool, sizeof(apr_thread_t)); + + if ((*new) == NULL) { + return APR_ENOMEM; + } + + (*new)->data = data; + (*new)->func = func; + (*new)->thread_name = (char*)apr_pstrdup(pool, threadName); + + stat = apr_pool_create(&(*new)->pool, pool); + if (stat != APR_SUCCESS) { + return stat; + } + + if (attr && attr->detach) { + flags |= NX_THR_DETACHED; + } + + (*new)->ctx = NXContextAlloc( + /* void(*start_routine)(void *arg) */ (void (*)(void *)) dummy_worker, + /* void *arg */ (*new), + /* int priority */ NX_PRIO_MED, + /* size_t stackSize */ stack_size, + /* unsigned long flags */ NX_CTX_NORMAL, + /* int *error */ &stat); + + stat = NXContextSetName( + /* NXContext_t ctx */ (*new)->ctx, + /* const char *name */ threadName); + + stat = NXThreadCreate( + /* NXContext_t context */ (*new)->ctx, + /* unsigned long flags */ flags, + /* NXThreadId_t *thread_id */ &(*new)->td); + + if (stat == 0) + return APR_SUCCESS; + + return(stat); /* if error */ +} + +apr_os_thread_t apr_os_thread_current() +{ + return NXThreadGetId(); +} + +int apr_os_thread_equal(apr_os_thread_t tid1, apr_os_thread_t tid2) +{ + return (tid1 == tid2); +} + +void apr_thread_yield() +{ + NXThreadYield(); +} + +apr_status_t apr_thread_exit(apr_thread_t *thd, + apr_status_t retval) +{ + thd->exitval = retval; + apr_pool_destroy(thd->pool); + NXThreadExit(NULL); + return APR_SUCCESS; +} + +apr_status_t apr_thread_join(apr_status_t *retval, + apr_thread_t *thd) +{ + apr_status_t stat; + NXThreadId_t dthr; + + if ((stat = NXThreadJoin(thd->td, &dthr, NULL)) == 0) { + *retval = thd->exitval; + return APR_SUCCESS; + } + else { + return stat; + } +} + +apr_status_t apr_thread_detach(apr_thread_t *thd) +{ + return APR_SUCCESS; +} + +apr_status_t apr_thread_data_get(void **data, const char *key, + apr_thread_t *thread) +{ + if (thread != NULL) { + return apr_pool_userdata_get(data, key, thread->pool); + } + else { + data = NULL; + return APR_ENOTHREAD; + } +} + +apr_status_t apr_thread_data_set(void *data, const char *key, + apr_status_t (*cleanup) (void *), + apr_thread_t *thread) +{ + if (thread != NULL) { + return apr_pool_userdata_set(data, key, cleanup, thread->pool); + } + else { + data = NULL; + return APR_ENOTHREAD; + } +} + +APR_DECLARE(apr_status_t) apr_os_thread_get(apr_os_thread_t **thethd, + apr_thread_t *thd) +{ + if (thd == NULL) { + return APR_ENOTHREAD; + } + *thethd = &(thd->td); + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_os_thread_put(apr_thread_t **thd, + apr_os_thread_t *thethd, + apr_pool_t *pool) +{ + if (pool == NULL) { + return APR_ENOPOOL; + } + if ((*thd) == NULL) { + (*thd) = (apr_thread_t *)apr_palloc(pool, sizeof(apr_thread_t)); + (*thd)->pool = pool; + } + (*thd)->td = *thethd; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_thread_once_init(apr_thread_once_t **control, + apr_pool_t *p) +{ + (*control) = apr_pcalloc(p, sizeof(**control)); + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_thread_once(apr_thread_once_t *control, + void (*func)(void)) +{ + if (!atomic_xchg(&control->value, 1)) { + func(); + } + return APR_SUCCESS; +} + +APR_POOL_IMPLEMENT_ACCESSOR(thread) + + diff --git a/threadproc/netware/threadpriv.c b/threadproc/netware/threadpriv.c new file mode 100644 index 0000000..54680a5 --- /dev/null +++ b/threadproc/netware/threadpriv.c @@ -0,0 +1,102 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_portable.h" +#include "apr_arch_threadproc.h" + +apr_status_t apr_threadkey_private_create(apr_threadkey_t **key, + void (*dest)(void *), apr_pool_t *pool) +{ + apr_status_t stat; + + (*key) = (apr_threadkey_t *)apr_palloc(pool, sizeof(apr_threadkey_t)); + if ((*key) == NULL) { + return APR_ENOMEM; + } + + (*key)->pool = pool; + + if ((stat = NXKeyCreate(NULL, dest, &(*key)->key)) == 0) { + return stat; + } + return stat; +} + +apr_status_t apr_threadkey_private_get(void **new, apr_threadkey_t *key) +{ + apr_status_t stat; + + if ((stat = NXKeyGetValue(key->key, new)) == 0) { + return APR_SUCCESS; + } + else { + return stat; + } +} + +apr_status_t apr_threadkey_private_set(void *priv, apr_threadkey_t *key) +{ + apr_status_t stat; + if ((stat = NXKeySetValue(key->key, priv)) == 0) { + return APR_SUCCESS; + } + else { + return stat; + } +} + +apr_status_t apr_threadkey_private_delete(apr_threadkey_t *key) +{ + apr_status_t stat; + if ((stat = NXKeyDelete(key->key)) == 0) { + return APR_SUCCESS; + } + return stat; +} + +apr_status_t apr_threadkey_data_get(void **data, const char *key, apr_threadkey_t *threadkey) +{ + return apr_pool_userdata_get(data, key, threadkey->pool); +} + +apr_status_t apr_threadkey_data_set(void *data, + const char *key, apr_status_t (*cleanup) (void *), + apr_threadkey_t *threadkey) +{ + return apr_pool_userdata_set(data, key, cleanup, threadkey->pool); +} + +apr_status_t apr_os_threadkey_get(apr_os_threadkey_t *thekey, + apr_threadkey_t *key) +{ + thekey = &(key->key); + return APR_SUCCESS; +} + +apr_status_t apr_os_threadkey_put(apr_threadkey_t **key, + apr_os_threadkey_t *thekey, apr_pool_t *pool) +{ + if (pool == NULL) { + return APR_ENOPOOL; + } + if ((*key) == NULL) { + (*key) = (apr_threadkey_t *)apr_palloc(pool, sizeof(apr_threadkey_t)); + (*key)->pool = pool; + } + (*key)->key = *thekey; + return APR_SUCCESS; +} + |