bottleneck testcase based on rubbos
[bottlenecks.git] / rubbos / app / tomcat-connectors-1.2.32-src / native / common / jk_shm.c
1 /*
2  *  Licensed to the Apache Software Foundation (ASF) under one or more
3  *  contributor license agreements.  See the NOTICE file distributed with
4  *  this work for additional information regarding copyright ownership.
5  *  The ASF licenses this file to You under the Apache License, Version 2.0
6  *  (the "License"); you may not use this file except in compliance with
7  *  the License.  You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  */
17
18 /***************************************************************************
19  * Description: Shared Memory support                                      *
20  * Author:      Mladen Turk <mturk@jboss.com>                              *
21  * Author:      Rainer Jung <rjung@apache.org>                             *
22  * Version:     $Revision: 704548 $                                        *
23  ***************************************************************************/
24
25 #include "jk_global.h"
26 #include "jk_pool.h"
27 #include "jk_util.h"
28 #include "jk_mt.h"
29 #include "jk_lb_worker.h"
30 #include "jk_ajp13_worker.h"
31 #include "jk_ajp14_worker.h"
32 #include "jk_shm.h"
33
34 /** jk shm header core data structure */
35 struct jk_shm_header_data
36 {
37     /* Shared memory magic JK_SHM_MAGIC */
38     char   magic[JK_SHM_MAGIC_SIZ];
39     size_t size;
40     size_t pos;
41     unsigned int childs;
42     unsigned int workers;
43     time_t modified;
44 };
45
46 typedef struct jk_shm_header_data jk_shm_header_data_t;
47
48 /** jk shm header record structure */
49 struct jk_shm_header
50 {
51     union {
52         jk_shm_header_data_t data;
53         char alignbuf[JK_SHM_ALIGN(sizeof(jk_shm_header_data_t))];
54     } h;
55     char   buf[1];
56 };
57
58 typedef struct jk_shm_header jk_shm_header_t;
59
60 /** jk shm structure */
61 struct jk_shm
62 {
63     size_t     size;
64     unsigned   ajp_workers;
65     unsigned   lb_sub_workers;
66     unsigned   lb_workers;
67     char       *filename;
68     char       *lockname;
69     int        fd;
70     int        fd_lock;
71     int        attached;
72     jk_shm_header_t  *hdr;
73     JK_CRIT_SEC       cs;
74 };
75
76 typedef struct jk_shm jk_shm_t;
77
78 static const char shm_signature[] = { JK_SHM_MAGIC };
79 static jk_shm_t jk_shmem = { 0, 0, 0, 0, NULL, NULL, -1, -1, 0, NULL};
80 static time_t jk_workers_modified_time = 0;
81 static time_t jk_workers_access_time = 0;
82 #if defined (WIN32)
83 static HANDLE jk_shm_map = NULL;
84 static HANDLE jk_shm_hlock = NULL;
85 #endif
86
87 /* Calculate needed shm size */
88 size_t jk_shm_calculate_size(jk_map_t *init_data, jk_logger_t *l)
89 {
90     char **worker_list;
91     unsigned i;
92     unsigned num_of_workers;
93     int num_of_ajp_workers = 0;
94     int num_of_lb_sub_workers = 0;
95     int num_of_lb_workers = 0;
96
97     JK_TRACE_ENTER(l);
98
99     if (jk_get_worker_list(init_data, &worker_list,
100                            &num_of_workers) == JK_FALSE) {
101         jk_log(l, JK_LOG_ERROR,
102                "Could not get worker list from map");
103         JK_TRACE_EXIT(l);
104         return 0;
105     }
106
107     for (i = 0; i < num_of_workers; i++) {
108         const char *type = jk_get_worker_type(init_data, worker_list[i]);
109
110         if (!strcmp(type, JK_AJP13_WORKER_NAME) ||
111             !strcmp(type, JK_AJP14_WORKER_NAME)) {
112             num_of_ajp_workers++;
113         }
114         else if (!strcmp(type, JK_LB_WORKER_NAME)) {
115             char **member_list;
116             unsigned num_of_members;
117             num_of_lb_workers++;
118             if (jk_get_lb_worker_list(init_data, worker_list[i],
119                                       &member_list, &num_of_members) == JK_FALSE) {
120                 jk_log(l, JK_LOG_ERROR,
121                        "Could not get member list for lb worker from map");
122             }
123             else {
124                 if (JK_IS_DEBUG_LEVEL(l))
125                     jk_log(l, JK_LOG_DEBUG, "worker %s of type %s has %u members",
126                            worker_list[i], JK_LB_WORKER_NAME, num_of_members);
127                 num_of_lb_sub_workers += num_of_members;
128             }
129         }
130     }
131     if (JK_IS_DEBUG_LEVEL(l))
132         jk_log(l, JK_LOG_DEBUG, "shared memory will contain %d ajp workers of size %d and %d lb workers of size %d with %d members of size %d+%d",
133                num_of_ajp_workers, JK_SHM_AJP_SIZE(1),
134                num_of_lb_workers, JK_SHM_LB_SIZE(1),
135                num_of_lb_sub_workers, JK_SHM_LB_SUB_SIZE(1), JK_SHM_AJP_SIZE(1));
136     jk_shmem.ajp_workers = num_of_ajp_workers;
137     jk_shmem.lb_sub_workers = num_of_lb_sub_workers;
138     jk_shmem.lb_workers = num_of_lb_workers;
139     JK_TRACE_EXIT(l);
140     return JK_SHM_AJP_SIZE(jk_shmem.ajp_workers) +
141            JK_SHM_LB_SUB_SIZE(jk_shmem.lb_sub_workers) +
142            JK_SHM_AJP_SIZE(jk_shmem.lb_sub_workers) +
143            JK_SHM_LB_SIZE(jk_shmem.lb_workers);
144 }
145
146
147 #if defined (WIN32) || defined(NETWARE)
148
149 /* Use plain memory */
150 int jk_shm_open(const char *fname, size_t sz, jk_logger_t *l)
151 {
152     int rc;
153     int attached = 0;
154     char lkname[MAX_PATH];
155     JK_TRACE_ENTER(l);
156     if (jk_shmem.hdr) {
157         if (JK_IS_DEBUG_LEVEL(l))
158             jk_log(l, JK_LOG_DEBUG, "Shared memory is already opened");
159         JK_TRACE_EXIT(l);
160         return 0;
161     }
162
163     jk_shmem.size = JK_SHM_ALIGN(sizeof(jk_shm_header_t) + sz);
164
165 #if defined (WIN32)
166     if (fname) {
167         jk_shm_map = CreateFileMapping(INVALID_HANDLE_VALUE,
168                                        NULL,
169                                        PAGE_READWRITE,
170                                        0,
171                                        (DWORD)(sizeof(jk_shm_header_t) + sz),
172                                        fname);
173         if (GetLastError() == ERROR_ALREADY_EXISTS) {
174             attached = 1;
175             if (jk_shm_map == NULL || jk_shm_map == INVALID_HANDLE_VALUE) {
176                 jk_shm_map = OpenFileMapping(PAGE_READWRITE, FALSE, fname);
177             }
178         }
179         if (jk_shm_map == NULL || jk_shm_map == INVALID_HANDLE_VALUE) {
180             JK_TRACE_EXIT(l);
181             return -1;
182         }
183         sprintf(lkname, "Global\\%s_MUTEX", fname);
184         if (attached) {
185             jk_shm_hlock = OpenMutex(MUTEX_ALL_ACCESS, FALSE, lkname);
186         }
187         else {
188             jk_shm_hlock = CreateMutex(NULL, FALSE, lkname);            
189         }
190         if (jk_shm_hlock == NULL || jk_shm_hlock == INVALID_HANDLE_VALUE) {
191             CloseHandle(jk_shm_map);
192             jk_shm_map = NULL;
193             JK_TRACE_EXIT(l);
194             return -1;
195         }
196         jk_shmem.hdr = (jk_shm_header_t *)MapViewOfFile(jk_shm_map,
197                                                         FILE_MAP_ALL_ACCESS,
198                                                         0,
199                                                         0,
200                                                         0);
201     }
202     else
203 #endif
204     jk_shmem.hdr = (jk_shm_header_t *)calloc(1, jk_shmem.size);
205     if (!jk_shmem.hdr) {
206 #if defined (WIN32)
207         if (jk_shm_map) {
208             CloseHandle(jk_shm_map);
209             jk_shm_map = NULL;
210         }
211         if (jk_shm_hlock) {
212             CloseHandle(jk_shm_hlock);
213             jk_shm_hlock = NULL;
214         }
215 #endif
216         JK_TRACE_EXIT(l);
217         return -1;
218     }
219     if (!jk_shmem.filename) {
220         if (fname)
221             jk_shmem.filename = strdup(fname);
222         else
223             jk_shmem.filename = strdup("memory");
224     }
225     jk_shmem.fd       = 0;
226     jk_shmem.attached = attached;
227     if (!attached) {
228         memcpy(jk_shmem.hdr->h.data.magic, shm_signature,
229                JK_SHM_MAGIC_SIZ);
230         jk_shmem.hdr->h.data.size = sz;
231         jk_shmem.hdr->h.data.childs = 1;
232     }
233     else {
234         jk_shmem.hdr->h.data.childs++;
235         /*
236          * Reset the shared memory so that
237          * alloc works even for attached memory.
238          * XXX: This might break already used memory
239          * if the number of workers change between
240          * open and attach or between two attach operations.
241          */
242         if (jk_shmem.hdr->h.data.childs > 1) {
243             if (JK_IS_DEBUG_LEVEL(l)) {
244                 jk_log(l, JK_LOG_DEBUG,
245                        "Resetting the shared memory for child %d",
246                        jk_shmem.hdr->h.data.childs);
247             }
248         }
249         jk_shmem.hdr->h.data.pos     = 0;
250         jk_shmem.hdr->h.data.workers = 0;
251     }
252     JK_INIT_CS(&(jk_shmem.cs), rc);
253     if (JK_IS_DEBUG_LEVEL(l))
254         jk_log(l, JK_LOG_DEBUG,
255                "%s shared memory %s size=%u free=%u addr=%#lx",
256                attached ? "Attached" : "Initialized",
257                jk_shm_name(), jk_shmem.size,
258                jk_shmem.hdr->h.data.size - jk_shmem.hdr->h.data.pos,
259                jk_shmem.hdr);
260     JK_TRACE_EXIT(l);
261     return 0;
262 }
263
264 int jk_shm_attach(const char *fname, size_t sz, jk_logger_t *l)
265 {
266     JK_TRACE_ENTER(l);
267     if (!jk_shm_open(fname, sz, l)) {
268         if (!jk_shmem.attached) {
269             jk_shmem.attached = 1;
270             if (JK_IS_DEBUG_LEVEL(l)) {
271                 jk_log(l, JK_LOG_DEBUG,
272                    "Attached shared memory %s [%d] size=%u free=%u addr=%#lx",
273                    jk_shm_name(), jk_shmem.hdr->h.data.childs, jk_shmem.size,
274                    jk_shmem.hdr->h.data.size - jk_shmem.hdr->h.data.pos,
275                    jk_shmem.hdr);
276             }
277         }
278         JK_TRACE_EXIT(l);
279         return 0;
280     }
281     else {
282         JK_TRACE_EXIT(l);
283         return -1;
284     }
285 }
286
287 void jk_shm_close()
288 {
289     if (jk_shmem.hdr) {
290         int rc;
291 #if defined (WIN32)
292         if (jk_shm_hlock) {
293             CloseHandle(jk_shm_hlock);
294             jk_shm_hlock = NULL;
295         }
296         if (jk_shm_map) {
297             --jk_shmem.hdr->h.data.childs;
298             UnmapViewOfFile(jk_shmem.hdr);
299             CloseHandle(jk_shm_map);
300             jk_shm_map = NULL;
301         }
302         else
303 #endif
304         free(jk_shmem.hdr);
305         JK_DELETE_CS(&(jk_shmem.cs), rc);
306     }
307     jk_shmem.hdr = NULL;
308     if (jk_shmem.filename) {
309         free(jk_shmem.filename);
310         jk_shmem.filename = NULL;
311     }
312 }
313
314 #else
315
316 #include <unistd.h>
317 #include <fcntl.h>
318 #include <errno.h>
319 #include <sys/stat.h>
320 #include <sys/mman.h>
321 #include <sys/uio.h>
322
323 #ifndef MAP_FAILED
324 #define MAP_FAILED  (-1)
325 #endif
326
327 #ifndef MAP_FILE
328 #define MAP_FILE    (0)
329 #endif
330
331 static int do_shm_open_lock(const char *fname, int attached, jk_logger_t *l)
332 {
333     int rc;
334     char flkname[256];
335 #ifdef AS400_UTF8
336     char *wptr;
337 #endif
338
339     JK_TRACE_ENTER(l);
340
341     if (attached && jk_shmem.lockname) {
342 #ifdef JK_SHM_LOCK_REOPEN
343         jk_shmem.fd_lock = open(jk_shmem.lockname, O_RDWR, 0666);
344 #else
345         errno = EINVAL;
346 #endif
347         if (jk_shmem.fd_lock == -1) {
348             rc = errno;
349             JK_TRACE_EXIT(l);
350             return rc;
351         }
352         if (JK_IS_DEBUG_LEVEL(l))
353             jk_log(l, JK_LOG_DEBUG,
354                    "Duplicated shared memory lock %s", jk_shmem.lockname);
355         JK_TRACE_EXIT(l);
356         return 0;
357     }
358
359     if (!jk_shmem.lockname) {
360 #ifdef JK_SHM_LOCK_REOPEN
361         int i;
362         jk_shmem.fd_lock = -1;
363         mode_t mask = umask(0);
364         for (i = 0; i < 8; i++) {
365             strcpy(flkname, "/tmp/jkshmlock.XXXXXX");
366             if (mktemp(flkname)) {
367                 jk_shmem.fd_lock = open(flkname, O_RDWR|O_CREAT|O_TRUNC, 0666);
368                 if (jk_shmem.fd_lock >= 0)
369                     break;
370             }
371         }
372         umask(mask);
373 #else
374         strcpy(flkname, fname);
375         strcat(flkname, ".lock");
376 #ifdef AS400_UTF8
377         wptr = (char *)malloc(strlen(flkname) + 1);
378         jk_ascii2ebcdic((char *)flkname, wptr);
379         jk_shmem.fd_lock = open(wptr, O_RDWR|O_CREAT|O_TRUNC, 0666);
380         free(wptr);
381 #else
382         jk_shmem.fd_lock = open(flkname, O_RDWR|O_CREAT|O_TRUNC, 0666);
383 #endif
384 #endif
385         if (jk_shmem.fd_lock == -1) {
386             rc = errno;
387             JK_TRACE_EXIT(l);
388             return rc;
389         }
390         jk_shmem.lockname = strdup(flkname);
391     }
392     else {
393         /* Nothing to do */
394         JK_TRACE_EXIT(l);
395         return 0;
396     }
397
398     if (ftruncate(jk_shmem.fd_lock, 1)) {
399         rc = errno;
400         close(jk_shmem.fd_lock);
401         jk_shmem.fd_lock = -1;
402         JK_TRACE_EXIT(l);
403         return rc;
404     }
405     if (lseek(jk_shmem.fd_lock, 0, SEEK_SET) != 0) {
406         rc = errno;
407         close(jk_shmem.fd_lock);
408         jk_shmem.fd_lock = -1;
409         return rc;
410     }
411     if (JK_IS_DEBUG_LEVEL(l))
412         jk_log(l, JK_LOG_DEBUG,
413                "Opened shared memory lock %s", jk_shmem.lockname);
414     JK_TRACE_EXIT(l);
415     return 0;
416 }
417
418 static int do_shm_open(const char *fname, int attached,
419                        size_t sz, jk_logger_t *l)
420 {
421     int rc;
422     int fd;
423     void *base;
424 #ifdef AS400_UTF8
425     char *wptr;
426 #endif
427
428     JK_TRACE_ENTER(l);
429     if (jk_shmem.hdr) {
430         /* Probably a call from vhost */
431         if (!attached)
432             attached = 1;
433     }
434     else if (attached) {
435         /* We should already have a header
436          * Use memory if we don't
437          */
438         JK_TRACE_EXIT(l);
439         return 0;
440     }
441     jk_shmem.size = JK_SHM_ALIGN(sizeof(jk_shm_header_t) + sz);
442
443     if (!fname) {
444         /* Use plain memory in case there is no file name */
445         if (!jk_shmem.filename)
446             jk_shmem.filename  = strdup("memory");
447         if (JK_IS_DEBUG_LEVEL(l))
448             jk_log(l, JK_LOG_DEBUG,
449                    "Using process memory as shared memory");
450         JK_TRACE_EXIT(l);
451         return 0;
452     }
453
454     if (!jk_shmem.filename) {
455         jk_shmem.filename = (char *)malloc(strlen(fname) + 32);
456         sprintf(jk_shmem.filename, "%s.%" JK_PID_T_FMT, fname, getpid());
457     }
458     if (!attached) {
459         size_t size;
460         jk_shmem.attached = 0;
461 #ifdef AS400_UTF8
462         wptr = (char *)malloc(strlen(jk_shmem.filename) + 1);
463         jk_ascii2ebcdic((char *)jk_shmem.filename, wptr);
464         fd = open(wptr, O_RDWR|O_CREAT|O_TRUNC, 0666);
465         free(wptr);
466 #else
467         fd = open(jk_shmem.filename, O_RDWR|O_CREAT|O_TRUNC, 0666);
468 #endif
469         if (fd == -1) {
470             jk_shmem.size = 0;
471             JK_TRACE_EXIT(l);
472             return errno;
473         }
474         size = lseek(fd, 0, SEEK_END);
475         if (size < jk_shmem.size) {
476             size = jk_shmem.size;
477             if (ftruncate(fd, jk_shmem.size)) {
478                 rc = errno;
479                 close(fd);
480 #ifdef  AS400_UTF8
481                 wptr = (char *)malloc(strlen(jk_shmem.filename) + 1);
482                 jk_ascii2ebcdic((char *)jk_shmem.filename, wptr);
483                 unlink(wptr);
484                 free(wptr);
485 #else
486                 unlink(jk_shmem.filename);
487 #endif
488                 jk_shmem.size = 0;
489                 JK_TRACE_EXIT(l);
490                 return rc;
491             }
492             if (JK_IS_DEBUG_LEVEL(l))
493                 jk_log(l, JK_LOG_DEBUG,
494                        "Truncated shared memory to %u", size);
495         }
496         if (lseek(fd, 0, SEEK_SET) != 0) {
497             rc = errno;
498             close(fd);
499 #ifdef  AS400_UTF8
500             wptr = (char *)malloc(strlen(jk_shmem.filename) + 1);
501             jk_ascii2ebcdic((char *)jk_shmem.filename, wptr);
502             unlink(wptr);
503             free(wptr);
504 #else
505             unlink(jk_shmem.filename);
506 #endif
507             jk_shmem.size = 0;
508             JK_TRACE_EXIT(l);
509             return rc;
510         }
511
512         base = mmap((caddr_t)0, jk_shmem.size,
513                     PROT_READ | PROT_WRITE,
514                     MAP_FILE | MAP_SHARED,
515                     fd, 0);
516         if (base == (caddr_t)MAP_FAILED || base == (caddr_t)0) {
517             rc = errno;
518             close(fd);
519 #ifdef  AS400_UTF8
520             wptr = (char *)malloc(strlen(jk_shmem.filename) + 1);
521             jk_ascii2ebcdic((char *)jk_shmem.filename, wptr);
522             unlink(wptr);
523             free(wptr);
524 #else
525             unlink(jk_shmem.filename);
526 #endif
527             jk_shmem.size = 0;
528             JK_TRACE_EXIT(l);
529             return rc;
530         }
531         jk_shmem.hdr = base;
532         jk_shmem.fd  = fd;
533         memset(jk_shmem.hdr, 0, jk_shmem.size);
534         memcpy(jk_shmem.hdr->h.data.magic, shm_signature, JK_SHM_MAGIC_SIZ);
535         jk_shmem.hdr->h.data.size = sz;
536         jk_shmem.hdr->h.data.childs = 1;
537         if (JK_IS_DEBUG_LEVEL(l))
538             jk_log(l, JK_LOG_DEBUG,
539                    "Initialized shared memory %s size=%u free=%u addr=%#lx",
540                    jk_shm_name(), jk_shmem.size,
541                    jk_shmem.hdr->h.data.size - jk_shmem.hdr->h.data.pos,
542                    jk_shmem.hdr);
543     }
544     else {
545         unsigned int nchild;
546         jk_shmem.hdr->h.data.childs++;
547         jk_shmem.attached = (int)getpid();
548         nchild = jk_shmem.hdr->h.data.childs;
549         if (JK_IS_DEBUG_LEVEL(l))
550             jk_log(l, JK_LOG_DEBUG,
551                    "Attached shared memory %s [%d] size=%u free=%u addr=%#lx",
552                    jk_shm_name(), nchild, jk_shmem.size,
553                    jk_shmem.hdr->h.data.size - jk_shmem.hdr->h.data.pos,
554                    jk_shmem.hdr);
555         /*
556          * Reset the shared memory so that
557          * alloc works even for attached memory.
558          * XXX: This might break already used memory
559          * if the number of workers change between
560          * open and attach or between two attach operations.
561          */
562         if (nchild > 1) {
563             if (JK_IS_DEBUG_LEVEL(l)) {
564                 jk_log(l, JK_LOG_DEBUG,
565                        "Resetting the shared memory for child %d",
566                        nchild);
567             }
568         }
569         jk_shmem.hdr->h.data.pos     = 0;
570         jk_shmem.hdr->h.data.workers = 0;
571     }
572     JK_INIT_CS(&(jk_shmem.cs), rc);
573     if ((rc = do_shm_open_lock(jk_shmem.filename, attached, l))) {
574         if (!attached) {
575             munmap((void *)jk_shmem.hdr, jk_shmem.size);
576             close(jk_shmem.fd);
577 #ifdef  AS400_UTF8
578             wptr = (char *)malloc(strlen(jk_shmem.filename) + 1);
579             jk_ascii2ebcdic((char *)jk_shmem.filename, wptr);
580             unlink(wptr);
581             free(wptr);
582 #else
583             unlink(jk_shmem.filename);
584 #endif
585         }
586         jk_shmem.hdr = NULL;
587         jk_shmem.fd  = -1;
588         JK_TRACE_EXIT(l);
589         return rc;
590     }
591     JK_TRACE_EXIT(l);
592     return 0;
593 }
594
595 int jk_shm_open(const char *fname, size_t sz, jk_logger_t *l)
596 {
597     return do_shm_open(fname, 0, sz, l);
598 }
599
600 int jk_shm_attach(const char *fname, size_t sz, jk_logger_t *l)
601 {
602     return do_shm_open(fname, 1, sz, l);
603 }
604
605 void jk_shm_close()
606 {
607     int rc;
608 #ifdef AS400_UTF8
609     char *wptr;
610 #endif
611
612     if (jk_shmem.hdr) {
613         --jk_shmem.hdr->h.data.childs;
614
615 #ifdef JK_SHM_LOCK_REOPEN
616         if (jk_shmem.fd_lock >= 0) {
617             close(jk_shmem.fd_lock);
618             jk_shmem.fd_lock = -1;
619         }
620 #endif
621         JK_DELETE_CS(&(jk_shmem.cs), rc);
622         if (jk_shmem.attached) {
623             int p = (int)getpid();
624             if (p == jk_shmem.attached) {
625                 /* In case this is a forked child
626                  * do not close the shared memory.
627                  * It will be closed by the parent.
628                  */
629                 jk_shmem.size = 0;
630                 jk_shmem.hdr  = NULL;
631                 jk_shmem.fd   = -1;
632                 return;
633             }
634         }
635         if (jk_shmem.fd >= 0) {
636             munmap((void *)jk_shmem.hdr, jk_shmem.size);
637             close(jk_shmem.fd);
638         }
639         if (jk_shmem.fd_lock >= 0)
640             close(jk_shmem.fd_lock);
641         if (jk_shmem.lockname) {
642 #ifdef  AS400_UTF8
643             wptr = (char *)malloc(strlen(jk_shmem.lockname) + 1);
644             jk_ascii2ebcdic((char *)jk_shmem.lockname, wptr);
645             unlink(wptr);
646             free(wptr);
647 #else
648             unlink(jk_shmem.lockname);
649 #endif
650             free(jk_shmem.lockname);
651             jk_shmem.lockname = NULL;
652         }
653         if (jk_shmem.filename) {
654 #ifdef  AS400_UTF8
655             wptr = (char *)malloc(strlen(jk_shmem.filename) + 1);
656             jk_ascii2ebcdic((char *)jk_shmem.filename, wptr);
657             unlink(wptr);
658             free(wptr);
659 #else
660             unlink(jk_shmem.filename);
661 #endif
662             free(jk_shmem.filename);
663             jk_shmem.filename = NULL;
664         }
665     }
666     jk_shmem.size    = 0;
667     jk_shmem.hdr     = NULL;
668     jk_shmem.fd      = -1;
669     jk_shmem.fd_lock = -1;
670 }
671
672
673 #endif
674
675 void *jk_shm_alloc(jk_pool_t *p, size_t size)
676 {
677     void *rc = NULL;
678
679     if (jk_shmem.hdr) {
680         size = JK_SHM_ALIGN(size);
681         if ((jk_shmem.hdr->h.data.size - jk_shmem.hdr->h.data.pos) >= size) {
682             rc = &(jk_shmem.hdr->buf[jk_shmem.hdr->h.data.pos]);
683             jk_shmem.hdr->h.data.pos += size;
684         }
685     }
686     else if (p)
687         rc = jk_pool_alloc(p, size);
688
689     return rc;
690 }
691
692 const char *jk_shm_name()
693 {
694     return jk_shmem.filename;
695 }
696
697
698 time_t jk_shm_get_workers_time()
699 {
700     if (jk_shmem.hdr)
701         return jk_shmem.hdr->h.data.modified;
702     else
703         return jk_workers_modified_time;
704 }
705
706 void jk_shm_set_workers_time(time_t t)
707 {
708     if (jk_shmem.hdr)
709         jk_shmem.hdr->h.data.modified = t;
710     else
711         jk_workers_modified_time = t;
712     jk_workers_access_time = t;
713 }
714
715 int jk_shm_is_modified()
716 {
717     time_t m = jk_shm_get_workers_time();
718     if (m != jk_workers_access_time)
719         return 1;
720     else
721         return 0;
722 }
723
724 void jk_shm_sync_access_time()
725 {
726     jk_workers_access_time = jk_shm_get_workers_time();
727 }
728
729 int jk_shm_lock()
730 {
731     int rc;
732     JK_ENTER_CS(&(jk_shmem.cs), rc);
733 #if defined (WIN32)
734     if (rc == JK_TRUE && jk_shm_hlock != NULL) {
735         DWORD rv = WaitForSingleObject(jk_shm_hlock, INFINITE);
736         if (rv == WAIT_OBJECT_0 || rv == WAIT_ABANDONED)
737             rc = JK_TRUE;
738         else
739             rc = JK_FALSE;         
740     }
741 #else    
742     if (rc == JK_TRUE && jk_shmem.fd_lock != -1) {
743         JK_ENTER_LOCK(jk_shmem.fd_lock, rc);
744     }
745 #endif
746     return rc;
747 }
748
749 int jk_shm_unlock()
750 {
751     int rc;
752     JK_LEAVE_CS(&(jk_shmem.cs), rc);
753 #if defined (WIN32)
754     if (rc == JK_TRUE && jk_shm_hlock != NULL) {
755         if (!ReleaseMutex(jk_shm_hlock))
756             rc = JK_FALSE;         
757     }
758 #else    
759     if (rc == JK_TRUE && jk_shmem.fd_lock != -1) {
760         JK_LEAVE_LOCK(jk_shmem.fd_lock, rc);
761     }
762 #endif
763     return rc;
764 }
765
766 jk_shm_ajp_worker_t *jk_shm_alloc_ajp_worker(jk_pool_t *p)
767 {
768     jk_shm_ajp_worker_t *w = (jk_shm_ajp_worker_t *)jk_shm_alloc(p, JK_SHM_AJP_WORKER_SIZE);
769     if (w) {
770         memset(w, 0, JK_SHM_AJP_WORKER_SIZE);
771         if (jk_shmem.hdr) {
772             jk_shmem.hdr->h.data.workers++;
773             w->h.id = jk_shmem.hdr->h.data.workers;
774             w->h.type = JK_AJP13_WORKER_TYPE;
775         }
776         else
777             w->h.id = -1;
778     }
779     return w;
780 }
781
782 jk_shm_lb_sub_worker_t *jk_shm_alloc_lb_sub_worker(jk_pool_t *p)
783 {
784     jk_shm_lb_sub_worker_t *w = (jk_shm_lb_sub_worker_t *)jk_shm_alloc(p, JK_SHM_LB_SUB_WORKER_SIZE);
785     if (w) {
786         memset(w, 0, JK_SHM_LB_SUB_WORKER_SIZE);
787         if (jk_shmem.hdr) {
788             jk_shmem.hdr->h.data.workers++;
789             w->h.id = jk_shmem.hdr->h.data.workers;
790             w->h.type = JK_LB_SUB_WORKER_TYPE;
791         }
792         else
793             w->h.id = -1;
794     }
795     return w;
796 }
797
798 jk_shm_lb_worker_t *jk_shm_alloc_lb_worker(jk_pool_t *p)
799 {
800     jk_shm_lb_worker_t *w = (jk_shm_lb_worker_t *)jk_shm_alloc(p, JK_SHM_LB_WORKER_SIZE);
801     if (w) {
802         memset(w, 0, JK_SHM_LB_WORKER_SIZE);
803         if (jk_shmem.hdr) {
804             jk_shmem.hdr->h.data.workers++;
805             w->h.id = jk_shmem.hdr->h.data.workers;
806             w->h.type = JK_LB_WORKER_TYPE;
807         }
808         else
809             w->h.id = -1;
810     }
811     return w;
812 }