1 diff -ruN php-5.1.6.old/ext/apc/apc.c php-5.1.6/ext/APC/apc.c
2 --- php-5.1.6.old/ext/apc/apc.c 1969-12-31 18:00:00.000000000 -0600
3 +++ php-5.1.6/ext/apc/apc.c 2007-04-02 18:05:30.000000000 -0500
6 + +----------------------------------------------------------------------+
8 + +----------------------------------------------------------------------+
9 + | Copyright (c) 2006 The PHP Group |
10 + +----------------------------------------------------------------------+
11 + | This source file is subject to version 3.01 of the PHP license, |
12 + | that is bundled with this package in the file LICENSE, and is |
13 + | available through the world-wide-web at the following url: |
14 + | http://www.php.net/license/3_01.txt |
15 + | If you did not receive a copy of the PHP license and are unable to |
16 + | obtain it through the world-wide-web, please send a note to |
17 + | license@php.net so we can mail you a copy immediately. |
18 + +----------------------------------------------------------------------+
19 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
20 + | George Schlossnagle <george@omniti.com> |
21 + | Rasmus Lerdorf <rasmus@php.net> |
22 + | Arun C. Murthy <arunc@yahoo-inc.com> |
23 + | Gopal Vijayaraghavan <gopalv@yahoo-inc.com> |
24 + +----------------------------------------------------------------------+
26 + This software was contributed to PHP by Community Connect Inc. in 2002
27 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
28 + Future revisions and derivatives of this source code must acknowledge
29 + Community Connect Inc. as the original contributor of this module by
30 + leaving this note intact in the source code.
32 + All other licensing and usage conditions are those of the PHP Group.
36 +/* $Id: apc.c,v 3.17 2007/03/17 14:01:41 gopalv Exp $ */
39 +#include <regex.h> /* for POSIX regular expressions */
42 +#define NELEMS(a) (sizeof(a)/sizeof((a)[0]))
44 +/* {{{ memory allocation wrappers */
46 +void* apc_emalloc(size_t n)
48 + void* p = malloc(n);
50 + apc_eprint("apc_emalloc: malloc failed to allocate %u bytes:", n);
55 +void* apc_erealloc(void* p, size_t n)
59 + apc_eprint("apc_erealloc: realloc failed to allocate %u bytes:", n);
64 +void apc_efree(void* p)
67 + apc_eprint("apc_efree: attempt to free null pointer");
72 +char* apc_estrdup(const char* s)
81 + dup = (char*) malloc(len+1);
83 + apc_eprint("apc_estrdup: malloc failed to allocate %u bytes:", len+1);
85 + memcpy(dup, s, len);
90 +void* apc_xstrdup(const char* s, apc_malloc_t f)
92 + return s != NULL ? apc_xmemcpy(s, strlen(s)+1, f) : NULL;
95 +void* apc_xmemcpy(const void* p, size_t n, apc_malloc_t f)
99 + if (p != NULL && (q = f(n)) != NULL) {
108 +/* {{{ console display functions */
110 +static void my_log(int level, const char* fmt, va_list args)
112 + static const char* level_strings[] = {
118 + static const int num_levels = NELEMS(level_strings);
121 + char* buf; /* for ctime */
127 + else if (level >= num_levels)
128 + level = num_levels-1;
131 + buf = ctime(&now); /* TODO: replace with reentrant impl */
134 + fprintf(stderr, "[%s] [%s] ", buf, level_strings[level]);
135 + vfprintf(stderr, fmt, args);
137 + if (fmt[0] != '\0' && fmt[strlen(fmt)-1] == ':') {
138 + fprintf(stderr, " %s", strerror(errno));
140 + fprintf(stderr, "\n");
142 + if (level == APC_ERROR) {
147 +void apc_log(int level, const char* fmt, ...)
150 + va_start(args, fmt);
151 + my_log(level, fmt, args);
155 +void apc_eprint(const char* fmt, ...)
158 + va_start(args, fmt);
159 + my_log(APC_ERROR, fmt, args);
163 +void apc_wprint(const char* fmt, ...)
166 + va_start(args, fmt);
167 + my_log(APC_WARNING, fmt, args);
171 +void apc_nprint(const char* fmt, ...)
174 + va_start(args, fmt);
175 + my_log(APC_NOTICE, fmt, args);
179 +void apc_dprint(const char* fmt, ...)
183 + va_start(args, fmt);
184 + my_log(APC_DBG, fmt, args);
191 +/* {{{ string and text manipulation */
193 +char* apc_append(const char* s, const char* t)
202 + p = (char*) apc_emalloc((slen + tlen + 1) * sizeof(char));
203 + memcpy(p, s, slen);
204 + memcpy(p + slen, t, tlen + 1);
209 +char* apc_substr(const char* s, int start, int length)
212 + int src_len = strlen(s);
214 + /* bring start into range */
218 + else if (start >= src_len) {
219 + start = src_len - 1;
222 + /* bring length into range */
223 + if (length < 0 || src_len - start < length) {
224 + length = src_len - start;
227 + /* create the substring */
228 + substr = apc_xmemcpy(s + start, length + 1, apc_emalloc);
229 + substr[length] = '\0';
233 +char** apc_tokenize(const char* s, char delim)
235 + char** tokens; /* array of tokens, NULL terminated */
236 + int size; /* size of tokens array */
237 + int n; /* index of next token in tokens array */
238 + int cur; /* current position in input string */
239 + int end; /* final legal position in input string */
240 + int next; /* position of next delimiter in input */
249 + end = strlen(s) - 1;
251 + tokens = (char**) apc_emalloc(size * sizeof(char*));
254 + while (cur <= end) {
255 + /* search for the next delimiter */
256 + char* p = strchr(s + cur, delim);
257 + next = p ? p-s : end+1;
259 + /* resize token array if necessary */
262 + tokens = (char**) apc_erealloc(tokens, size * sizeof(char*));
265 + /* save the current token */
266 + tokens[n] = apc_substr(s, cur, next-cur);
268 + tokens[++n] = NULL;
277 +/* {{{ filesystem functions */
280 +int apc_win32_stat(const char *path, struct stat *buf TSRMLS_DC)
282 + char rpath[MAXPATHLEN];
283 + BY_HANDLE_FILE_INFORMATION fi;
286 + if (VCWD_STAT(path, buf)) {
290 + VCWD_REALPATH(path, rpath);
291 + f = CreateFile(rpath, 0, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_ATTRIBUTE_READONLY, NULL);
292 + GetFileInformationByHandle(f, &fi);
293 + buf->st_ino = (ino_t)fi.nFileIndexLow;
299 +int apc_search_paths(const char* filename, const char* path, apc_fileinfo_t* fileinfo)
303 + int exec_fname_length;
308 + assert(filename && fileinfo);
310 + if (IS_ABSOLUTE_PATH(filename, strlen(filename)) && apc_stat(filename, &fileinfo->st_buf) == 0) {
311 + strncpy(fileinfo->fullpath, filename, MAXPATHLEN);
315 + paths = apc_tokenize(path, DEFAULT_DIR_SEPARATOR);
319 + /* for each directory in paths, look for filename inside */
320 + for (i = 0; paths[i]; i++) {
321 + snprintf(fileinfo->fullpath, sizeof(fileinfo->fullpath), "%s%c%s", paths[i], DEFAULT_SLASH, filename);
322 + if (apc_stat(fileinfo->fullpath, &fileinfo->st_buf) == 0) {
328 + /* check in path of the calling scripts' current working directory */
329 + /* modified from main/streams/plain_wrapper.c */
330 + if(!found && zend_is_executing(TSRMLS_C)) {
331 + exec_fname = zend_get_executed_filename(TSRMLS_C);
332 + exec_fname_length = strlen(exec_fname);
333 + while((--exec_fname_length >= 0) && !IS_SLASH(exec_fname[exec_fname_length]));
334 + if((exec_fname && exec_fname[0] != '[') && exec_fname_length > 0) {
335 + /* not: [no active file] or no path */
336 + memcpy(fileinfo->fullpath, exec_fname, exec_fname_length);
337 + fileinfo->fullpath[exec_fname_length] = DEFAULT_SLASH;
338 + strcpy(fileinfo->fullpath +exec_fname_length +1, filename);
339 + /* apc_wprint("filename: %s, exec_fname: %s, fileinfo->fullpath: %s", filename, exec_fname, fileinfo->fullpath); */
340 + if (apc_stat(fileinfo->fullpath, &fileinfo->st_buf) == 0) {
346 + /* free the value returned by apc_tokenize */
347 + for (i = 0; paths[i]; i++) {
348 + apc_efree(paths[i]);
352 + return found ? 0 : -1;
357 +/* {{{ regular expression wrapper functions */
361 + unsigned char type;
364 +void* apc_regex_compile_array(char* patterns[])
373 + /* count the number of patterns in patterns */
374 + for (npat = 0; patterns[npat] != NULL; npat++) {}
379 + /* allocate the array of compiled expressions */
380 + regs = (apc_regex**) apc_emalloc(sizeof(apc_regex*) * (npat + 1));
381 + for (i = 0; i <= npat; i++) {
382 + regs[i] = (apc_regex *) apc_emalloc(sizeof(apc_regex));
383 + regs[i]->reg = NULL;
384 + regs[i]->type = APC_NEGATIVE_MATCH;
387 + /* compile the expressions */
388 + for (i = 0; i < npat; i++) {
389 + char *pattern = patterns[i];
390 + if(pattern[0]=='+') { regs[i]->type = APC_POSITIVE_MATCH; pattern = patterns[i]+sizeof(char); }
391 + else if(pattern[0]=='-') { regs[i]->type = APC_NEGATIVE_MATCH; pattern = patterns[i]+sizeof(char); }
393 + regs[i]->reg = (regex_t*) apc_emalloc(sizeof(regex_t));
395 + if (regcomp(regs[i]->reg, pattern, REG_EXTENDED | REG_NOSUB) != 0) {
396 + apc_wprint("apc_regex_compile_array: invalid expression '%s'",
399 + apc_regex_destroy_array(regs);
405 + return (void*) regs;
408 +void apc_regex_destroy_array(void* p)
411 + apc_regex** regs = (apc_regex**) p;
414 + for (i = 0; regs[i]->reg != NULL; i++) {
415 + regfree(regs[i]->reg);
416 + apc_efree(regs[i]->reg);
417 + apc_efree(regs[i]);
423 +int apc_regex_match_array(void* p, const char* input)
431 + regs = (apc_regex**) p;
432 + for (i = 0; regs[i]->reg != NULL; i++)
433 + if (regexec(regs[i]->reg, input, 0, NULL, 0) == 0)
434 + return (int)(regs[i]->type);
441 +/* {{{ crc32 implementation */
443 +/* this table was generated by crc32gen() */
444 +static unsigned int crc32tab[] = {
445 + /* 0 */ 0x00000000, 0x3b83984b, 0x77073096, 0x4c84a8dd,
446 + /* 4 */ 0xee0e612c, 0xd58df967, 0x990951ba, 0xa28ac9f1,
447 + /* 8 */ 0x076dc419, 0x3cee5c52, 0x706af48f, 0x4be96cc4,
448 + /* 12 */ 0xe963a535, 0xd2e03d7e, 0x9e6495a3, 0xa5e70de8,
449 + /* 16 */ 0x0edb8832, 0x35581079, 0x79dcb8a4, 0x425f20ef,
450 + /* 20 */ 0xe0d5e91e, 0xdb567155, 0x97d2d988, 0xac5141c3,
451 + /* 24 */ 0x09b64c2b, 0x3235d460, 0x7eb17cbd, 0x4532e4f6,
452 + /* 28 */ 0xe7b82d07, 0xdc3bb54c, 0x90bf1d91, 0xab3c85da,
453 + /* 32 */ 0x1db71064, 0x2634882f, 0x6ab020f2, 0x5133b8b9,
454 + /* 36 */ 0xf3b97148, 0xc83ae903, 0x84be41de, 0xbf3dd995,
455 + /* 40 */ 0x1adad47d, 0x21594c36, 0x6ddde4eb, 0x565e7ca0,
456 + /* 44 */ 0xf4d4b551, 0xcf572d1a, 0x83d385c7, 0xb8501d8c,
457 + /* 48 */ 0x136c9856, 0x28ef001d, 0x646ba8c0, 0x5fe8308b,
458 + /* 52 */ 0xfd62f97a, 0xc6e16131, 0x8a65c9ec, 0xb1e651a7,
459 + /* 56 */ 0x14015c4f, 0x2f82c404, 0x63066cd9, 0x5885f492,
460 + /* 60 */ 0xfa0f3d63, 0xc18ca528, 0x8d080df5, 0xb68b95be,
461 + /* 64 */ 0x3b6e20c8, 0x00edb883, 0x4c69105e, 0x77ea8815,
462 + /* 68 */ 0xd56041e4, 0xeee3d9af, 0xa2677172, 0x99e4e939,
463 + /* 72 */ 0x3c03e4d1, 0x07807c9a, 0x4b04d447, 0x70874c0c,
464 + /* 76 */ 0xd20d85fd, 0xe98e1db6, 0xa50ab56b, 0x9e892d20,
465 + /* 80 */ 0x35b5a8fa, 0x0e3630b1, 0x42b2986c, 0x79310027,
466 + /* 84 */ 0xdbbbc9d6, 0xe038519d, 0xacbcf940, 0x973f610b,
467 + /* 88 */ 0x32d86ce3, 0x095bf4a8, 0x45df5c75, 0x7e5cc43e,
468 + /* 92 */ 0xdcd60dcf, 0xe7559584, 0xabd13d59, 0x9052a512,
469 + /* 96 */ 0x26d930ac, 0x1d5aa8e7, 0x51de003a, 0x6a5d9871,
470 + /* 100 */ 0xc8d75180, 0xf354c9cb, 0xbfd06116, 0x8453f95d,
471 + /* 104 */ 0x21b4f4b5, 0x1a376cfe, 0x56b3c423, 0x6d305c68,
472 + /* 108 */ 0xcfba9599, 0xf4390dd2, 0xb8bda50f, 0x833e3d44,
473 + /* 112 */ 0x2802b89e, 0x138120d5, 0x5f058808, 0x64861043,
474 + /* 116 */ 0xc60cd9b2, 0xfd8f41f9, 0xb10be924, 0x8a88716f,
475 + /* 120 */ 0x2f6f7c87, 0x14ece4cc, 0x58684c11, 0x63ebd45a,
476 + /* 124 */ 0xc1611dab, 0xfae285e0, 0xb6662d3d, 0x8de5b576,
477 + /* 128 */ 0x76dc4190, 0x4d5fd9db, 0x01db7106, 0x3a58e94d,
478 + /* 132 */ 0x98d220bc, 0xa351b8f7, 0xefd5102a, 0xd4568861,
479 + /* 136 */ 0x71b18589, 0x4a321dc2, 0x06b6b51f, 0x3d352d54,
480 + /* 140 */ 0x9fbfe4a5, 0xa43c7cee, 0xe8b8d433, 0xd33b4c78,
481 + /* 144 */ 0x7807c9a2, 0x438451e9, 0x0f00f934, 0x3483617f,
482 + /* 148 */ 0x9609a88e, 0xad8a30c5, 0xe10e9818, 0xda8d0053,
483 + /* 152 */ 0x7f6a0dbb, 0x44e995f0, 0x086d3d2d, 0x33eea566,
484 + /* 156 */ 0x91646c97, 0xaae7f4dc, 0xe6635c01, 0xdde0c44a,
485 + /* 160 */ 0x6b6b51f4, 0x50e8c9bf, 0x1c6c6162, 0x27eff929,
486 + /* 164 */ 0x856530d8, 0xbee6a893, 0xf262004e, 0xc9e19805,
487 + /* 168 */ 0x6c0695ed, 0x57850da6, 0x1b01a57b, 0x20823d30,
488 + /* 172 */ 0x8208f4c1, 0xb98b6c8a, 0xf50fc457, 0xce8c5c1c,
489 + /* 176 */ 0x65b0d9c6, 0x5e33418d, 0x12b7e950, 0x2934711b,
490 + /* 180 */ 0x8bbeb8ea, 0xb03d20a1, 0xfcb9887c, 0xc73a1037,
491 + /* 184 */ 0x62dd1ddf, 0x595e8594, 0x15da2d49, 0x2e59b502,
492 + /* 188 */ 0x8cd37cf3, 0xb750e4b8, 0xfbd44c65, 0xc057d42e,
493 + /* 192 */ 0x4db26158, 0x7631f913, 0x3ab551ce, 0x0136c985,
494 + /* 196 */ 0xa3bc0074, 0x983f983f, 0xd4bb30e2, 0xef38a8a9,
495 + /* 200 */ 0x4adfa541, 0x715c3d0a, 0x3dd895d7, 0x065b0d9c,
496 + /* 204 */ 0xa4d1c46d, 0x9f525c26, 0xd3d6f4fb, 0xe8556cb0,
497 + /* 208 */ 0x4369e96a, 0x78ea7121, 0x346ed9fc, 0x0fed41b7,
498 + /* 212 */ 0xad678846, 0x96e4100d, 0xda60b8d0, 0xe1e3209b,
499 + /* 216 */ 0x44042d73, 0x7f87b538, 0x33031de5, 0x088085ae,
500 + /* 220 */ 0xaa0a4c5f, 0x9189d414, 0xdd0d7cc9, 0xe68ee482,
501 + /* 224 */ 0x5005713c, 0x6b86e977, 0x270241aa, 0x1c81d9e1,
502 + /* 228 */ 0xbe0b1010, 0x8588885b, 0xc90c2086, 0xf28fb8cd,
503 + /* 232 */ 0x5768b525, 0x6ceb2d6e, 0x206f85b3, 0x1bec1df8,
504 + /* 236 */ 0xb966d409, 0x82e54c42, 0xce61e49f, 0xf5e27cd4,
505 + /* 240 */ 0x5edef90e, 0x655d6145, 0x29d9c998, 0x125a51d3,
506 + /* 244 */ 0xb0d09822, 0x8b530069, 0xc7d7a8b4, 0xfc5430ff,
507 + /* 248 */ 0x59b33d17, 0x6230a55c, 0x2eb40d81, 0x153795ca,
508 + /* 252 */ 0xb7bd5c3b, 0x8c3ec470, 0xc0ba6cad, 0xfb39f4e6,
511 +unsigned int apc_crc32(const char* buf, int len)
517 + /* preconditioning */
520 + for (i = 0; i < len; i++) {
521 + k = (crc ^ buf[i]) & 0x000000FF;
522 + crc = ((crc >> 8) & 0x00FFFFFF) ^ crc32tab[k];
525 + /* postconditioning */
529 +/* crc32gen: generate the nth (0..255) crc32 table value */
531 +static unsigned long crc32gen(int n)
537 + for (i = 8; i >= 0; i--) {
539 + crc = (crc >> 1) ^ 0xEDB88320;
554 + * c-basic-offset: 4
556 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
557 + * vim<600: expandtab sw=4 ts=4 sts=4
559 diff -ruN php-5.1.6.old/ext/apc/apc_cache.c php-5.1.6/ext/APC/apc_cache.c
560 --- php-5.1.6.old/ext/apc/apc_cache.c 1969-12-31 18:00:00.000000000 -0600
561 +++ php-5.1.6/ext/apc/apc_cache.c 2007-04-02 18:05:30.000000000 -0500
564 + +----------------------------------------------------------------------+
566 + +----------------------------------------------------------------------+
567 + | Copyright (c) 2006 The PHP Group |
568 + +----------------------------------------------------------------------+
569 + | This source file is subject to version 3.01 of the PHP license, |
570 + | that is bundled with this package in the file LICENSE, and is |
571 + | available through the world-wide-web at the following url: |
572 + | http://www.php.net/license/3_01.txt |
573 + | If you did not receive a copy of the PHP license and are unable to |
574 + | obtain it through the world-wide-web, please send a note to |
575 + | license@php.net so we can mail you a copy immediately. |
576 + +----------------------------------------------------------------------+
577 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
578 + | Rasmus Lerdorf <rasmus@php.net> |
579 + | Arun C. Murthy <arunc@yahoo-inc.com> |
580 + | Gopal Vijayaraghavan <gopalv@yahoo-inc.com> |
581 + +----------------------------------------------------------------------+
583 + This software was contributed to PHP by Community Connect Inc. in 2002
584 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
585 + Future revisions and derivatives of this source code must acknowledge
586 + Community Connect Inc. as the original contributor of this module by
587 + leaving this note intact in the source code.
589 + All other licensing and usage conditions are those of the PHP Group.
593 +/* $Id: apc_cache.c,v 3.140 2007/04/02 22:57:10 rasmus Exp $ */
595 +#include "apc_cache.h"
596 +#include "apc_lock.h"
597 +#include "apc_sma.h"
598 +#include "apc_globals.h"
600 +#include "ext/standard/php_var.h"
601 +#include "ext/standard/php_smart_str.h"
603 +/* TODO: rehash when load factor exceeds threshold */
605 +#define CHECK(p) { if ((p) == NULL) return NULL; }
607 +/* {{{ locking macros */
608 +#define CREATE_LOCK(lock) apc_lck_create(NULL, 0, 1, lock)
609 +#define DESTROY_LOCK(c) apc_lck_destroy(c->header->lock)
610 +#define LOCK(c) { HANDLE_BLOCK_INTERRUPTIONS(); apc_lck_lock(c->header->lock); }
611 +#define RDLOCK(c) { HANDLE_BLOCK_INTERRUPTIONS(); apc_lck_rdlock(c->header->lock); }
612 +#define UNLOCK(c) { apc_lck_unlock(c->header->lock); HANDLE_UNBLOCK_INTERRUPTIONS(); }
615 +/* {{{ struct definition: slot_t */
616 +typedef struct slot_t slot_t;
618 + apc_cache_key_t key; /* slot key */
619 + apc_cache_entry_t* value; /* slot value */
620 + slot_t* next; /* next slot in linked list */
621 + int num_hits; /* number of hits to this bucket */
622 + time_t creation_time; /* time slot was initialized */
623 + time_t deletion_time; /* time slot was removed from cache */
624 + time_t access_time; /* time slot was last accessed */
628 +/* {{{ struct definition: header_t
629 + Any values that must be shared among processes should go in here. */
630 +typedef struct header_t header_t;
632 + apc_lck_t lock; /* read/write lock (exclusive blocking cache lock) */
633 + apc_lck_t wrlock; /* write lock (non-blocking used to prevent cache slams) */
634 + int num_hits; /* total successful hits in cache */
635 + int num_misses; /* total unsuccessful hits in cache */
636 + int num_inserts; /* total successful inserts in cache */
637 + slot_t* deleted_list; /* linked list of to-be-deleted slots */
638 + time_t start_time; /* time the above counters were reset */
639 + int expunges; /* total number of expunges */
640 + zend_bool busy; /* Flag to tell clients when we are busy cleaning the cache */
641 + int num_entries; /* Statistic on the number of entries */
642 + size_t mem_size; /* Statistic on the memory size used by this cache */
646 +/* {{{ struct definition: apc_cache_t */
647 +struct apc_cache_t {
648 + void* shmaddr; /* process (local) address of shared cache */
649 + header_t* header; /* cache header (stored in SHM) */
650 + slot_t** slots; /* array of cache slots (stored in SHM) */
651 + int num_slots; /* number of slots in cache */
652 + int gc_ttl; /* maximum time on GC list for a slot */
653 + int ttl; /* if slot is needed and entry's access time is older than this ttl, remove it */
657 +/* {{{ struct definition local_slot_t */
658 +typedef struct local_slot_t local_slot_t;
659 +struct local_slot_t {
660 + slot_t *original; /* the original slot in shm */
661 + int num_hits; /* number of hits */
662 + apc_cache_entry_t *value; /* shallow copy of slot->value */
663 + local_slot_t *next; /* only for dead list */
666 +/* {{{ struct definition apc_local_cache_t */
667 +struct apc_local_cache_t {
668 + apc_cache_t* shmcache; /* the real cache in shm */
669 + local_slot_t* slots; /* process (local) cache of objects */
670 + local_slot_t* dead_list; /* list of objects pending removal */
671 + int num_slots; /* number of slots in cache */
672 + int ttl; /* time to live */
673 + int num_hits; /* number of hits */
674 + int generation; /* every generation lives between expunges */
678 +/* {{{ key_equals */
679 +#define key_equals(a, b) (a.inode==b.inode && a.device==b.device)
683 +static unsigned int hash(apc_cache_key_t key)
685 + return key.data.file.device + key.data.file.inode;
689 +/* {{{ string_nhash_8 */
690 +static unsigned int string_nhash_8(const char *s, size_t len)
692 + register const unsigned int *iv = (const unsigned int *)s;
693 + register unsigned int h = 0;
694 + register const unsigned int *e = (const unsigned int *)(s + len - (len % sizeof(unsigned int)));
698 + h = (h << 7) | (h >> ((8*sizeof(unsigned int)) - 7));
700 + s = (const char *)iv;
701 + for(len %= sizeof(unsigned int);len;len--) {
711 +slot_t* make_slot(apc_cache_key_t key, apc_cache_entry_t* value, slot_t* next, time_t t)
713 + slot_t* p = apc_sma_malloc(sizeof(slot_t));
714 + if (!p) return NULL;
716 + if(value->type == APC_CACHE_ENTRY_USER) {
717 + char *identifier = (char*) apc_xstrdup(key.data.user.identifier, apc_sma_malloc);
722 + key.data.user.identifier = identifier;
723 + } else if(key.type == APC_CACHE_KEY_FPFILE) {
724 + char *fullpath = (char*) apc_xstrdup(key.data.fpfile.fullpath, apc_sma_malloc);
729 + key.data.fpfile.fullpath = fullpath;
735 + p->creation_time = t;
736 + p->access_time = t;
737 + p->deletion_time = 0;
743 +static void free_slot(slot_t* slot)
745 + if(slot->value->type == APC_CACHE_ENTRY_USER) {
746 + apc_sma_free((char *)slot->key.data.user.identifier);
747 + } else if(slot->key.type == APC_CACHE_KEY_FPFILE) {
748 + apc_sma_free((char *)slot->key.data.fpfile.fullpath);
750 + apc_cache_free_entry(slot->value);
751 + apc_sma_free(slot);
755 +/* {{{ remove_slot */
756 +static void remove_slot(apc_cache_t* cache, slot_t** slot)
758 + slot_t* dead = *slot;
759 + *slot = (*slot)->next;
761 + cache->header->mem_size -= dead->value->mem_size;
762 + cache->header->num_entries--;
763 + if (dead->value->ref_count <= 0) {
767 + dead->next = cache->header->deleted_list;
768 + dead->deletion_time = time(0);
769 + cache->header->deleted_list = dead;
774 +/* {{{ process_pending_removals */
775 +static void process_pending_removals(apc_cache_t* cache)
780 + /* This function scans the list of removed cache entries and deletes any
781 + * entry whose reference count is zero (indicating that it is no longer
782 + * being executed) or that has been on the pending list for more than
783 + * cache->gc_ttl seconds (we issue a warning in the latter case).
786 + if (!cache->header->deleted_list)
789 + slot = &cache->header->deleted_list;
792 + while (*slot != NULL) {
793 + int gc_sec = cache->gc_ttl ? (now - (*slot)->deletion_time) : 0;
795 + if ((*slot)->value->ref_count <= 0 || gc_sec > cache->gc_ttl) {
796 + slot_t* dead = *slot;
798 + if (dead->value->ref_count > 0) {
799 + switch(dead->value->type) {
800 + case APC_CACHE_ENTRY_FILE:
801 + apc_log(APC_WARNING, "GC cache entry '%s' (dev=%d ino=%d) "
802 + "was on gc-list for %d seconds", dead->value->data.file.filename,
803 + dead->key.data.file.device, dead->key.data.file.inode, gc_sec);
805 + case APC_CACHE_ENTRY_USER:
806 + apc_log(APC_WARNING, "GC cache entry '%s' "
807 + "was on gc-list for %d seconds", dead->value->data.user.info, gc_sec);
811 + *slot = dead->next;
815 + slot = &(*slot)->next;
821 +/* {{{ prevent_garbage_collection */
822 +static void prevent_garbage_collection(apc_cache_entry_t* entry)
824 + /* set reference counts on zend objects to an arbitrarily high value to
825 + * prevent garbage collection after execution */
827 + enum { BIG_VALUE = 1000 };
829 + if(entry->data.file.op_array) {
830 + entry->data.file.op_array->refcount[0] = BIG_VALUE;
832 + if (entry->data.file.functions) {
834 + apc_function_t* fns = entry->data.file.functions;
835 + for (i=0; fns[i].function != NULL; i++) {
836 +#ifdef ZEND_ENGINE_2
837 + *(fns[i].function->op_array.refcount) = BIG_VALUE;
839 + fns[i].function->op_array.refcount[0] = BIG_VALUE;
843 + if (entry->data.file.classes) {
845 + apc_class_t* classes = entry->data.file.classes;
846 + for (i=0; classes[i].class_entry != NULL; i++) {
847 +#ifdef ZEND_ENGINE_2
848 + classes[i].class_entry->refcount = BIG_VALUE;
850 + classes[i].class_entry->refcount[0] = BIG_VALUE;
857 +/* {{{ apc_cache_create */
858 +apc_cache_t* apc_cache_create(int size_hint, int gc_ttl, int ttl)
860 + apc_cache_t* cache;
865 + num_slots = size_hint > 0 ? size_hint*2 : 2000;
867 + cache = (apc_cache_t*) apc_emalloc(sizeof(apc_cache_t));
868 + cache_size = sizeof(header_t) + num_slots*sizeof(slot_t*);
870 + cache->shmaddr = apc_sma_malloc(cache_size);
871 + memset(cache->shmaddr, 0, cache_size);
873 + cache->header = (header_t*) cache->shmaddr;
874 + cache->header->num_hits = 0;
875 + cache->header->num_misses = 0;
876 + cache->header->deleted_list = NULL;
877 + cache->header->start_time = time(NULL);
878 + cache->header->expunges = 0;
879 + cache->header->busy = 0;
881 + cache->slots = (slot_t**) (((char*) cache->shmaddr) + sizeof(header_t));
882 + cache->num_slots = num_slots;
883 + cache->gc_ttl = gc_ttl;
885 + CREATE_LOCK(cache->header->lock);
886 +#if NONBLOCKING_LOCK_AVAILABLE
887 + CREATE_LOCK(cache->header->wrlock);
889 + for (i = 0; i < num_slots; i++) {
890 + cache->slots[i] = NULL;
897 +/* {{{ apc_cache_destroy */
898 +void apc_cache_destroy(apc_cache_t* cache)
900 + DESTROY_LOCK(cache);
905 +/* {{{ apc_cache_clear */
906 +void apc_cache_clear(apc_cache_t* cache)
913 + cache->header->busy = 1;
914 + cache->header->num_hits = 0;
915 + cache->header->num_misses = 0;
916 + cache->header->start_time = time(NULL);
917 + cache->header->expunges = 0;
919 + for (i = 0; i < cache->num_slots; i++) {
920 + slot_t* p = cache->slots[i];
922 + remove_slot(cache, &p);
924 + cache->slots[i] = NULL;
927 + cache->header->busy = 0;
932 +/* {{{ apc_cache_expunge */
933 +void apc_cache_expunge(apc_cache_t* cache, time_t t)
941 + * If cache->ttl is not set, we wipe out the entire cache when
942 + * we run out of space.
945 + cache->header->busy = 1;
946 + cache->header->expunges++;
947 + for (i = 0; i < cache->num_slots; i++) {
948 + slot_t* p = cache->slots[i];
950 + remove_slot(cache, &p);
952 + cache->slots[i] = NULL;
954 + cache->header->busy = 0;
960 + * If the ttl for the cache is set we walk through and delete stale
961 + * entries. For the user cache that is slightly confusing since
962 + * we have the individual entry ttl's we can look at, but that would be
963 + * too much work. So if you want the user cache expunged, set a high
964 + * default apc.user_ttl and still provide a specific ttl for each entry
969 + cache->header->busy = 1;
970 + cache->header->expunges++;
971 + for (i = 0; i < cache->num_slots; i++) {
972 + p = &cache->slots[i];
975 + * For the user cache we look at the individual entry ttl values
976 + * and if not set fall back to the default ttl for the user cache
978 + if((*p)->value->type == APC_CACHE_ENTRY_USER) {
979 + if((*p)->value->data.user.ttl) {
980 + if((*p)->creation_time + (*p)->value->data.user.ttl < t) {
981 + remove_slot(cache, p);
984 + } else if(cache->ttl) {
985 + if((*p)->creation_time + cache->ttl < t) {
986 + remove_slot(cache, p);
990 + } else if((*p)->access_time < (t - cache->ttl)) {
991 + remove_slot(cache, p);
997 + cache->header->busy = 0;
1003 +/* {{{ apc_cache_insert */
1004 +int apc_cache_insert(apc_cache_t* cache,
1005 + apc_cache_key_t key,
1006 + apc_cache_entry_t* value,
1015 +#ifdef __DEBUG_APC__
1016 + fprintf(stderr,"Inserting [%s]\n", value->data.file.filename);
1020 + process_pending_removals(cache);
1022 + if(key.type == APC_CACHE_KEY_FILE) slot = &cache->slots[hash(key) % cache->num_slots];
1023 + else slot = &cache->slots[string_nhash_8(key.data.fpfile.fullpath, key.data.fpfile.fullpath_len) % cache->num_slots];
1026 + if(key.type == (*slot)->key.type) {
1027 + if(key.type == APC_CACHE_KEY_FILE) {
1028 + if(key_equals((*slot)->key.data.file, key.data.file)) {
1029 + /* If existing slot for the same device+inode is different, remove it and insert the new version */
1030 + if ((*slot)->key.mtime != key.mtime) {
1031 + remove_slot(cache, slot);
1036 + } else if(cache->ttl && (*slot)->access_time < (t - cache->ttl)) {
1037 + remove_slot(cache, slot);
1040 + } else { /* APC_CACHE_KEY_FPFILE */
1041 + if(!memcmp((*slot)->key.data.fpfile.fullpath, key.data.fpfile.fullpath, key.data.fpfile.fullpath_len+1)) {
1042 + /* Hrm.. it's already here, remove it and insert new one */
1043 + remove_slot(cache, slot);
1045 + } else if(cache->ttl && (*slot)->access_time < (t - cache->ttl)) {
1046 + remove_slot(cache, slot);
1051 + slot = &(*slot)->next;
1054 + if ((*slot = make_slot(key, value, *slot, t)) == NULL) {
1059 + cache->header->mem_size += value->mem_size;
1060 + cache->header->num_entries++;
1061 + cache->header->num_inserts++;
1068 +/* {{{ apc_cache_user_insert */
1069 +int apc_cache_user_insert(apc_cache_t* cache, apc_cache_key_t key, apc_cache_entry_t* value, time_t t, int exclusive TSRMLS_DC)
1072 + size_t* mem_size_ptr = NULL;
1079 + process_pending_removals(cache);
1081 + slot = &cache->slots[string_nhash_8(key.data.user.identifier, key.data.user.identifier_len) % cache->num_slots];
1083 + if (APCG(mem_size_ptr) != NULL) {
1084 + mem_size_ptr = APCG(mem_size_ptr);
1085 + APCG(mem_size_ptr) = NULL;
1089 + if (!memcmp((*slot)->key.data.user.identifier, key.data.user.identifier, key.data.user.identifier_len)) {
1091 + * At this point we have found the user cache entry. If we are doing
1092 + * an exclusive insert (apc_add) we are going to bail right away if
1093 + * the user entry already exists and it has no ttl, or
1094 + * there is a ttl and the entry has not timed out yet.
1096 + if(exclusive && ( !(*slot)->value->data.user.ttl ||
1097 + ( (*slot)->value->data.user.ttl && ((*slot)->creation_time + (*slot)->value->data.user.ttl) >= t )
1102 + remove_slot(cache, slot);
1106 + * This is a bit nasty. The idea here is to do runtime cleanup of the linked list of
1107 + * slot entries so we don't always have to skip past a bunch of stale entries. We check
1108 + * for staleness here and get rid of them by first checking to see if the cache has a global
1109 + * access ttl on it and removing entries that haven't been accessed for ttl seconds and secondly
1110 + * we see if the entry has a hard ttl on it and remove it if it has been around longer than its ttl
1112 + if((cache->ttl && (*slot)->access_time < (t - cache->ttl)) ||
1113 + ((*slot)->value->data.user.ttl && ((*slot)->creation_time + (*slot)->value->data.user.ttl) < t)) {
1114 + remove_slot(cache, slot);
1117 + slot = &(*slot)->next;
1120 + if (mem_size_ptr != NULL) {
1121 + APCG(mem_size_ptr) = mem_size_ptr;
1124 + if ((*slot = make_slot(key, value, *slot, t)) == NULL) {
1128 + if (APCG(mem_size_ptr) != NULL) {
1129 + value->mem_size = *APCG(mem_size_ptr);
1130 + cache->header->mem_size += *APCG(mem_size_ptr);
1132 + cache->header->num_entries++;
1133 + cache->header->num_inserts++;
1140 +/* {{{ apc_cache_find_slot */
1141 +slot_t* apc_cache_find_slot(apc_cache_t* cache, apc_cache_key_t key, time_t t)
1144 + volatile slot_t* retval = NULL;
1147 + if(key.type == APC_CACHE_KEY_FILE) slot = &cache->slots[hash(key) % cache->num_slots];
1148 + else slot = &cache->slots[string_nhash_8(key.data.fpfile.fullpath, key.data.fpfile.fullpath_len) % cache->num_slots];
1151 + if(key.type == (*slot)->key.type) {
1152 + if(key.type == APC_CACHE_KEY_FILE) {
1153 + if(key_equals((*slot)->key.data.file, key.data.file)) {
1154 + if((*slot)->key.mtime != key.mtime) {
1155 + remove_slot(cache, slot);
1156 + cache->header->num_misses++;
1160 + (*slot)->num_hits++;
1161 + (*slot)->value->ref_count++;
1162 + (*slot)->access_time = t;
1163 + prevent_garbage_collection((*slot)->value);
1164 + cache->header->num_hits++;
1167 + return (slot_t*)retval;
1169 + } else { /* APC_CACHE_KEY_FPFILE */
1170 + if(!memcmp((*slot)->key.data.fpfile.fullpath, key.data.fpfile.fullpath, key.data.fpfile.fullpath_len+1)) {
1172 + (*slot)->num_hits++;
1173 + (*slot)->value->ref_count++;
1174 + (*slot)->access_time = t;
1175 + prevent_garbage_collection((*slot)->value);
1176 + cache->header->num_hits++;
1179 + return (slot_t*)retval;
1183 + slot = &(*slot)->next;
1185 + cache->header->num_misses++;
1191 +/* {{{ apc_cache_find */
1192 +apc_cache_entry_t* apc_cache_find(apc_cache_t* cache, apc_cache_key_t key, time_t t)
1194 + slot_t * slot = apc_cache_find_slot(cache, key, t);
1195 + return (slot) ? slot->value : NULL;
1199 +/* {{{ apc_cache_user_find */
1200 +apc_cache_entry_t* apc_cache_user_find(apc_cache_t* cache, char *strkey, int keylen, time_t t)
1203 + volatile apc_cache_entry_t* value = NULL;
1207 + slot = &cache->slots[string_nhash_8(strkey, keylen) % cache->num_slots];
1210 + if (!memcmp((*slot)->key.data.user.identifier, strkey, keylen)) {
1211 + /* Check to make sure this entry isn't expired by a hard TTL */
1212 + if((*slot)->value->data.user.ttl && ((*slot)->creation_time + (*slot)->value->data.user.ttl) < t) {
1213 + remove_slot(cache, slot);
1217 + /* Otherwise we are fine, increase counters and return the cache entry */
1218 + (*slot)->num_hits++;
1219 + (*slot)->value->ref_count++;
1220 + (*slot)->access_time = t;
1222 + cache->header->num_hits++;
1223 + value = (*slot)->value;
1225 + return (apc_cache_entry_t*)value;
1227 + slot = &(*slot)->next;
1235 +/* {{{ apc_cache_user_delete */
1236 +int apc_cache_user_delete(apc_cache_t* cache, char *strkey, int keylen)
1242 + slot = &cache->slots[string_nhash_8(strkey, keylen) % cache->num_slots];
1245 + if (!memcmp((*slot)->key.data.user.identifier, strkey, keylen)) {
1246 + remove_slot(cache, slot);
1250 + slot = &(*slot)->next;
1258 +/* {{{ apc_cache_release */
1259 +void apc_cache_release(apc_cache_t* cache, apc_cache_entry_t* entry)
1261 + /* local cache refcount-- is done in apc_local_cache_cleanup */
1262 + if(entry->local) return;
1265 + entry->ref_count--;
1270 +/* {{{ apc_cache_make_file_key */
1271 +int apc_cache_make_file_key(apc_cache_key_t* key,
1272 + const char* filename,
1273 + const char* include_path,
1277 + static char canon_path[MAXPATHLEN];
1278 + struct stat *tmp_buf=NULL;
1279 + struct apc_fileinfo_t fileinfo = { {0}, };
1282 + assert(key != NULL);
1284 + if (!filename || !SG(request_info).path_translated) {
1285 +#ifdef __DEBUG_APC__
1286 + fprintf(stderr,"No filename and no path_translated - bailing\n");
1291 + len = strlen(filename);
1292 + if(APCG(fpstat)==0) {
1293 + if(IS_ABSOLUTE_PATH(filename,len)) {
1294 + key->data.fpfile.fullpath = filename;
1295 + key->data.fpfile.fullpath_len = len;
1297 + key->type = APC_CACHE_KEY_FPFILE;
1299 + if(!realpath(filename, canon_path)) {
1300 + fprintf(stderr, "realpath failed to canonicalize %s - bailing\n", filename);
1303 + key->data.fpfile.fullpath = canon_path;
1304 + key->data.fpfile.fullpath_len = strlen(canon_path);
1306 + key->type = APC_CACHE_KEY_FPFILE;
1311 + if(!strcmp(SG(request_info).path_translated, filename)) {
1312 + tmp_buf = sapi_get_stat(TSRMLS_C); /* Apache has already done this stat() for us */
1315 + fileinfo.st_buf = *tmp_buf;
1317 + if (apc_search_paths(filename, include_path, &fileinfo) != 0) {
1318 +#ifdef __DEBUG_APC__
1319 + fprintf(stderr,"Stat failed %s - bailing (%s) (%d)\n",filename,SG(request_info).path_translated);
1325 + if(APCG(max_file_size) < fileinfo.st_buf.st_size) {
1326 +#ifdef __DEBUG_APC__
1327 + fprintf(stderr,"File is too big %s (%d - %ld) - bailing\n",filename,t,fileinfo.st_buf.st_size);
1333 + * This is a bit of a hack.
1335 + * Here I am checking to see if the file is at least 2 seconds old.
1336 + * The idea is that if the file is currently being written to then its
1337 + * mtime is going to match or at most be 1 second off of the current
1338 + * request time and we want to avoid caching files that have not been
1339 + * completely written. Of course, people should be using atomic
1340 + * mechanisms to push files onto live web servers, but adding this
1341 + * tiny safety is easier than educating the world. This is now
1342 + * configurable, but the default is still 2 seconds.
1344 + if(APCG(file_update_protection) && (t - fileinfo.st_buf.st_mtime < APCG(file_update_protection))) {
1345 +#ifdef __DEBUG_APC__
1346 + fprintf(stderr,"File is too new %s (%d - %d) - bailing\n",filename,t,fileinfo.st_buf.st_mtime);
1351 + key->data.file.device = fileinfo.st_buf.st_dev;
1352 + key->data.file.inode = fileinfo.st_buf.st_ino;
1354 + * If working with content management systems that like to munge the mtime,
1355 + * it might be appropriate to key off of the ctime to be immune to systems
1356 + * that try to backdate a template. If the mtime is set to something older
1357 + * than the previous mtime of a template we will obviously never see this
1358 + * "older" template. At some point the Smarty templating system did this.
1359 + * I generally disagree with using the ctime here because you lose the
1360 + * ability to warm up new content by saving it to a temporary file, hitting
1361 + * it once to cache it and then renaming it into its permanent location so
1362 + * set the apc.stat_ctime=true to enable this check.
1364 + if(APCG(stat_ctime)) {
1365 + key->mtime = (fileinfo.st_buf.st_ctime > fileinfo.st_buf.st_mtime) ? fileinfo.st_buf.st_ctime : fileinfo.st_buf.st_mtime;
1367 + key->mtime = fileinfo.st_buf.st_mtime;
1369 + key->type = APC_CACHE_KEY_FILE;
1374 +/* {{{ apc_cache_make_user_key */
1375 +int apc_cache_make_user_key(apc_cache_key_t* key, char* identifier, int identifier_len, const time_t t)
1377 + assert(key != NULL);
1382 + key->data.user.identifier = identifier;
1383 + key->data.user.identifier_len = identifier_len;
1385 + key->type = APC_CACHE_KEY_USER;
1390 +/* {{{ apc_cache_make_file_entry */
1391 +apc_cache_entry_t* apc_cache_make_file_entry(const char* filename,
1392 + zend_op_array* op_array,
1393 + apc_function_t* functions,
1394 + apc_class_t* classes)
1396 + apc_cache_entry_t* entry;
1398 + entry = (apc_cache_entry_t*) apc_sma_malloc(sizeof(apc_cache_entry_t));
1399 + if (!entry) return NULL;
1401 + entry->data.file.filename = apc_xstrdup(filename, apc_sma_malloc);
1402 + if(!entry->data.file.filename) {
1403 +#ifdef __DEBUG_APC__
1404 + fprintf(stderr,"apc_cache_make_file_entry: entry->data.file.filename is NULL - bailing\n");
1406 + apc_sma_free(entry);
1409 +#ifdef __DEBUG_APC__
1410 + fprintf(stderr,"apc_cache_make_file_entry: entry->data.file.filename is [%s]\n",entry->data.file.filename);
1412 + entry->data.file.op_array = op_array;
1413 + entry->data.file.functions = functions;
1414 + entry->data.file.classes = classes;
1415 + entry->type = APC_CACHE_ENTRY_FILE;
1416 + entry->ref_count = 0;
1417 + entry->mem_size = 0;
1418 + entry->autofiltered = 0;
1424 +/* {{{ apc_cache_store_zval */
1425 +zval* apc_cache_store_zval(zval* dst, const zval* src, apc_malloc_t allocate, apc_free_t deallocate)
1427 + smart_str buf = {0};
1428 + php_serialize_data_t var_hash;
1431 + if((src->type & ~IS_CONSTANT_INDEX) == IS_OBJECT) {
1433 + CHECK(dst = (zval*) allocate(sizeof(zval)));
1436 + PHP_VAR_SERIALIZE_INIT(var_hash);
1437 + php_var_serialize(&buf, (zval**)&src, &var_hash TSRMLS_CC);
1438 + PHP_VAR_SERIALIZE_DESTROY(var_hash);
1440 + dst->type = IS_NULL; /* in case we fail */
1442 + dst->type = src->type & ~IS_CONSTANT_INDEX;
1443 + dst->value.str.len = buf.len;
1444 + CHECK(dst->value.str.val = apc_xmemcpy(buf.c, buf.len+1, allocate));
1445 + dst->type = src->type;
1446 + smart_str_free(&buf);
1451 + /* Maintain a list of zvals we've copied to properly handle recursive structures */
1452 + HashTable *old = APCG(copied_zvals);
1453 + APCG(copied_zvals) = emalloc(sizeof(HashTable));
1454 + zend_hash_init(APCG(copied_zvals), 0, NULL, NULL, 0);
1456 + dst = apc_copy_zval(dst, src, allocate, deallocate);
1458 + if(APCG(copied_zvals)) {
1459 + zend_hash_destroy(APCG(copied_zvals));
1460 + efree(APCG(copied_zvals));
1463 + APCG(copied_zvals) = old;
1470 +/* {{{ apc_cache_fetch_zval */
1471 +zval* apc_cache_fetch_zval(zval* dst, const zval* src, apc_malloc_t allocate, apc_free_t deallocate)
1474 + if((src->type & ~IS_CONSTANT_INDEX) == IS_OBJECT) {
1475 + php_unserialize_data_t var_hash;
1476 + const unsigned char *p = (unsigned char*)Z_STRVAL_P(src);
1478 + PHP_VAR_UNSERIALIZE_INIT(var_hash);
1479 + if(!php_var_unserialize(&dst, &p, p + Z_STRLEN_P(src), &var_hash TSRMLS_CC)) {
1480 + PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
1482 + php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Error at offset %ld of %d bytes", (long)((char*)p - Z_STRVAL_P(src)), Z_STRLEN_P(src));
1483 + dst->type = IS_NULL;
1485 + PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
1489 + /* Maintain a list of zvals we've copied to properly handle recursive structures */
1490 + HashTable *old = APCG(copied_zvals);
1491 + APCG(copied_zvals) = emalloc(sizeof(HashTable));
1492 + zend_hash_init(APCG(copied_zvals), 0, NULL, NULL, 0);
1494 + dst = apc_copy_zval(dst, src, allocate, deallocate);
1496 + if(APCG(copied_zvals)) {
1497 + zend_hash_destroy(APCG(copied_zvals));
1498 + efree(APCG(copied_zvals));
1501 + APCG(copied_zvals) = old;
1508 +/* {{{ apc_cache_free_zval */
1509 +void apc_cache_free_zval(zval* src, apc_free_t deallocate)
1512 + if ((src->type & ~IS_CONSTANT_INDEX) == IS_OBJECT) {
1513 + if (src->value.str.val) {
1514 + deallocate(src->value.str.val);
1518 + /* Maintain a list of zvals we've copied to properly handle recursive structures */
1519 + HashTable *old = APCG(copied_zvals);
1520 + APCG(copied_zvals) = emalloc(sizeof(HashTable));
1521 + zend_hash_init(APCG(copied_zvals), 0, NULL, NULL, 0);
1523 + apc_free_zval(src, deallocate);
1525 + if(APCG(copied_zvals)) {
1526 + zend_hash_destroy(APCG(copied_zvals));
1527 + efree(APCG(copied_zvals));
1530 + APCG(copied_zvals) = old;
1535 +/* {{{ apc_cache_make_user_entry */
1536 +apc_cache_entry_t* apc_cache_make_user_entry(const char* info, int info_len, const zval* val, const unsigned int ttl)
1538 + apc_cache_entry_t* entry;
1540 + entry = (apc_cache_entry_t*) apc_sma_malloc(sizeof(apc_cache_entry_t));
1541 + if (!entry) return NULL;
1543 + entry->data.user.info = apc_xmemcpy(info, info_len, apc_sma_malloc);
1544 + entry->data.user.info_len = info_len;
1545 + if(!entry->data.user.info) {
1546 + apc_sma_free(entry);
1549 + entry->data.user.val = apc_cache_store_zval(NULL, val, apc_sma_malloc, apc_sma_free);
1550 + if(!entry->data.user.val) {
1551 + apc_sma_free(entry->data.user.info);
1552 + apc_sma_free(entry);
1555 + INIT_PZVAL(entry->data.user.val);
1556 + entry->data.user.ttl = ttl;
1557 + entry->type = APC_CACHE_ENTRY_USER;
1558 + entry->ref_count = 0;
1559 + entry->mem_size = 0;
1560 + entry->autofiltered = 0;
1566 +/* {{{ apc_cache_free_entry */
1567 +void apc_cache_free_entry(apc_cache_entry_t* entry)
1569 + if (entry != NULL) {
1570 + assert(entry->ref_count == 0);
1571 + switch(entry->type) {
1572 + case APC_CACHE_ENTRY_FILE:
1573 + apc_sma_free(entry->data.file.filename);
1574 + apc_free_op_array(entry->data.file.op_array, apc_sma_free);
1575 + apc_free_functions(entry->data.file.functions, apc_sma_free);
1576 + apc_free_classes(entry->data.file.classes, apc_sma_free);
1578 + case APC_CACHE_ENTRY_USER:
1579 + apc_sma_free(entry->data.user.info);
1580 + apc_cache_free_zval(entry->data.user.val, apc_sma_free);
1583 + apc_sma_free(entry);
1588 +/* {{{ apc_cache_info */
1589 +apc_cache_info_t* apc_cache_info(apc_cache_t* cache, zend_bool limited)
1591 + apc_cache_info_t* info;
1595 + if(!cache) return NULL;
1599 + info = (apc_cache_info_t*) apc_emalloc(sizeof(apc_cache_info_t));
1604 + info->num_slots = cache->num_slots;
1605 + info->ttl = cache->ttl;
1606 + info->num_hits = cache->header->num_hits;
1607 + info->num_misses = cache->header->num_misses;
1608 + info->list = NULL;
1609 + info->deleted_list = NULL;
1610 + info->start_time = cache->header->start_time;
1611 + info->expunges = cache->header->expunges;
1612 + info->mem_size = cache->header->mem_size;
1613 + info->num_entries = cache->header->num_entries;
1614 + info->num_inserts = cache->header->num_inserts;
1617 + /* For each hashtable slot */
1618 + for (i = 0; i < info->num_slots; i++) {
1619 + p = cache->slots[i];
1620 + for (; p != NULL; p = p->next) {
1621 + apc_cache_link_t* link = (apc_cache_link_t*) apc_emalloc(sizeof(apc_cache_link_t));
1623 + if(p->value->type == APC_CACHE_ENTRY_FILE) {
1624 + link->data.file.filename = apc_xstrdup(p->value->data.file.filename, apc_emalloc);
1625 + link->data.file.device = p->key.data.file.device;
1626 + link->data.file.inode = p->key.data.file.inode;
1627 + link->type = APC_CACHE_ENTRY_FILE;
1628 + } else if(p->value->type == APC_CACHE_ENTRY_USER) {
1629 + link->data.user.info = apc_xmemcpy(p->value->data.user.info, p->value->data.user.info_len, apc_emalloc);
1630 + link->data.user.ttl = p->value->data.user.ttl;
1631 + link->type = APC_CACHE_ENTRY_USER;
1633 + link->num_hits = p->num_hits;
1634 + link->mtime = p->key.mtime;
1635 + link->creation_time = p->creation_time;
1636 + link->deletion_time = p->deletion_time;
1637 + link->access_time = p->access_time;
1638 + link->ref_count = p->value->ref_count;
1639 + link->mem_size = p->value->mem_size;
1640 + link->next = info->list;
1641 + info->list = link;
1645 + /* For each slot pending deletion */
1646 + for (p = cache->header->deleted_list; p != NULL; p = p->next) {
1647 + apc_cache_link_t* link = (apc_cache_link_t*) apc_emalloc(sizeof(apc_cache_link_t));
1649 + if(p->value->type == APC_CACHE_ENTRY_FILE) {
1650 + link->data.file.filename = apc_xstrdup(p->value->data.file.filename, apc_emalloc);
1651 + if(p->key.type == APC_CACHE_KEY_FILE) {
1652 + link->data.file.device = p->key.data.file.device;
1653 + link->data.file.inode = p->key.data.file.inode;
1654 + } else { /* This is a no-stat fullpath file entry */
1655 + link->data.file.device = 0;
1656 + link->data.file.inode = 0;
1658 + link->type = APC_CACHE_ENTRY_FILE;
1659 + } else if(p->value->type == APC_CACHE_ENTRY_USER) {
1660 + link->data.user.info = apc_xmemcpy(p->value->data.user.info, p->value->data.user.info_len, apc_emalloc);
1661 + link->data.user.ttl = p->value->data.user.ttl;
1662 + link->type = APC_CACHE_ENTRY_USER;
1664 + link->num_hits = p->num_hits;
1665 + link->mtime = p->key.mtime;
1666 + link->creation_time = p->creation_time;
1667 + link->deletion_time = p->deletion_time;
1668 + link->access_time = p->access_time;
1669 + link->ref_count = p->value->ref_count;
1670 + link->mem_size = p->value->mem_size;
1671 + link->next = info->deleted_list;
1672 + info->deleted_list = link;
1681 +/* {{{ apc_cache_free_info */
1682 +void apc_cache_free_info(apc_cache_info_t* info)
1684 + apc_cache_link_t* p = info->list;
1685 + apc_cache_link_t* q = NULL;
1686 + while (p != NULL) {
1689 + if(q->type == APC_CACHE_ENTRY_FILE) apc_efree(q->data.file.filename);
1690 + else if(q->type == APC_CACHE_ENTRY_USER) apc_efree(q->data.user.info);
1693 + p = info->deleted_list;
1694 + while (p != NULL) {
1697 + if(q->type == APC_CACHE_ENTRY_FILE) apc_efree(q->data.file.filename);
1698 + else if(q->type == APC_CACHE_ENTRY_USER) apc_efree(q->data.user.info);
1705 +/* {{{ apc_cache_unlock */
1706 +void apc_cache_unlock(apc_cache_t* cache)
1712 +/* {{{ apc_cache_busy */
1713 +zend_bool apc_cache_busy(apc_cache_t* cache)
1715 + return cache->header->busy;
1719 +#if NONBLOCKING_LOCK_AVAILABLE
1720 +/* {{{ apc_cache_write_lock */
1721 +zend_bool apc_cache_write_lock(apc_cache_t* cache)
1723 + return apc_lck_nb_lock(cache->header->wrlock);
1727 +/* {{{ apc_cache_write_unlock */
1728 +void apc_cache_write_unlock(apc_cache_t* cache)
1730 + apc_lck_unlock(cache->header->wrlock);
1735 +/* {{{ make_local_slot */
1736 +static local_slot_t* make_local_slot(apc_local_cache_t* cache, local_slot_t* lslot, slot_t* slot)
1738 + apc_cache_entry_t* value;
1740 + value = apc_emalloc(sizeof(apc_cache_entry_t));
1741 + memcpy(value, slot->value, sizeof(apc_cache_entry_t)); /* bitwise copy */
1744 + lslot->original = slot;
1745 + lslot->value = value;
1746 + lslot->num_hits++;
1748 + return lslot; /* for what joy ? ... consistency */
1752 +/* {{{ free_local_slot */
1753 +static void free_local_slot(apc_local_cache_t* cache, local_slot_t* lslot)
1755 + local_slot_t * dead = NULL;
1756 + if(!lslot->original) return;
1758 + /* TODO: Bad design to allocate memory in a free_* - fix when bored (hehe) */
1759 + dead = apc_emalloc(sizeof(local_slot_t));
1760 + memcpy(dead, lslot, sizeof(local_slot_t)); /* bitwise copy */
1762 + lslot->original = NULL;
1763 + lslot->value = NULL;
1765 + dead->next = cache->dead_list;
1766 + cache->dead_list = dead;
1770 +/* {{{ apc_local_cache_create */
1771 +apc_local_cache_t* apc_local_cache_create(apc_cache_t *shmcache, int num_slots, int ttl)
1773 + apc_local_cache_t* cache = NULL;
1775 + cache = (apc_local_cache_t*) apc_emalloc(sizeof(apc_local_cache_t));
1777 + cache->slots = (local_slot_t*) (apc_emalloc(sizeof(local_slot_t) * num_slots));
1778 + memset(cache->slots, 0, sizeof(local_slot_t) * num_slots);
1780 + cache->shmcache = shmcache;
1781 + cache->num_slots = num_slots;
1783 + cache->num_hits = 0;
1784 + cache->generation = shmcache->header->expunges;
1785 + cache->dead_list = NULL;
1791 +/* {{{ apc_local_cache_cleanup */
1792 +void apc_local_cache_cleanup(apc_local_cache_t* cache) {
1793 + local_slot_t * lslot;
1794 + time_t t = time(0);
1797 + for(i = 0; i < cache->num_slots; i++) {
1798 + slot_t * slot = cache->slots[i].original;
1799 + if((slot && slot->access_time < (t - cache->ttl)) ||
1800 + cache->generation != cache->shmcache->header->expunges) {
1801 + free_local_slot(cache, &cache->slots[i]);
1805 + LOCK(cache->shmcache);
1806 + for(lslot = cache->dead_list; lslot != NULL; lslot = lslot->next) {
1807 + lslot->original->num_hits += lslot->num_hits;
1808 + lslot->original->value->ref_count--; /* apc_cache_release(cache->shmcache, lslot->original->value); */
1809 + apc_efree(lslot->value);
1811 + UNLOCK(cache->shmcache);
1813 + cache->dead_list = NULL;
1817 +/* {{{ apc_local_cache_destroy */
1818 +void apc_local_cache_destroy(apc_local_cache_t* cache)
1821 + for(i = 0; i < cache->num_slots; i++) {
1822 + free_local_slot(cache, &cache->slots[i]);
1825 + apc_local_cache_cleanup(cache);
1827 + LOCK(cache->shmcache);
1828 + cache->shmcache->header->num_hits += cache->num_hits;
1829 + UNLOCK(cache->shmcache);
1831 + apc_efree(cache->slots);
1836 +/* {{{ apc_local_cache_find */
1837 +apc_cache_entry_t* apc_local_cache_find(apc_local_cache_t* cache, apc_cache_key_t key, time_t t)
1840 + local_slot_t* lslot;
1842 + if(key.type == APC_CACHE_KEY_FILE) lslot = &cache->slots[hash(key) % cache->num_slots];
1843 + else lslot = &cache->slots[string_nhash_8(key.data.fpfile.fullpath, key.data.fpfile.fullpath_len) % cache->num_slots];
1845 + slot = lslot->original;
1847 + if(slot && key.type == slot->key.type) {
1848 + if(slot->access_time < (t - cache->ttl)) {
1851 + if(key.type == APC_CACHE_KEY_FILE &&
1852 + key_equals(slot->key.data.file, key.data.file)) {
1853 + if(slot->key.mtime != key.mtime) {
1854 + free_local_slot(cache, lslot);
1857 + return lslot->value;
1858 + } else if(key.type == APC_CACHE_KEY_FPFILE) {
1859 + if(!memcmp(slot->key.data.fpfile.fullpath, key.data.fpfile.fullpath, key.data.fpfile.fullpath_len+1)) {
1860 + return lslot->value;
1865 + if(apc_cache_busy(cache->shmcache)) {
1869 + slot = apc_cache_find_slot(cache->shmcache, key, t);
1871 + if(!slot) return NULL;
1873 + /* i.e maintain a sort of top list */
1874 + if(lslot->original == NULL || (lslot->original->num_hits + lslot->num_hits) < slot->num_hits) {
1875 + free_local_slot(cache, lslot);
1876 + make_local_slot(cache, lslot, slot);
1877 + return lslot->value;
1879 + return slot->value;
1884 + * Local variables:
1886 + * c-basic-offset: 4
1888 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
1889 + * vim<600: expandtab sw=4 ts=4 sts=4
1891 diff -ruN php-5.1.6.old/ext/apc/apc_cache.h php-5.1.6/ext/APC/apc_cache.h
1892 --- php-5.1.6.old/ext/apc/apc_cache.h 1969-12-31 18:00:00.000000000 -0600
1893 +++ php-5.1.6/ext/apc/apc_cache.h 2007-04-02 18:05:30.000000000 -0500
1896 + +----------------------------------------------------------------------+
1898 + +----------------------------------------------------------------------+
1899 + | Copyright (c) 2006 The PHP Group |
1900 + +----------------------------------------------------------------------+
1901 + | This source file is subject to version 3.01 of the PHP license, |
1902 + | that is bundled with this package in the file LICENSE, and is |
1903 + | available through the world-wide-web at the following url: |
1904 + | http://www.php.net/license/3_01.txt. |
1905 + | If you did not receive a copy of the PHP license and are unable to |
1906 + | obtain it through the world-wide-web, please send a note to |
1907 + | license@php.net so we can mail you a copy immediately. |
1908 + +----------------------------------------------------------------------+
1909 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
1910 + | Rasmus Lerdorf <rasmus@php.net> |
1911 + +----------------------------------------------------------------------+
1913 + This software was contributed to PHP by Community Connect Inc. in 2002
1914 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
1915 + Future revisions and derivatives of this source code must acknowledge
1916 + Community Connect Inc. as the original contributor of this module by
1917 + leaving this note intact in the source code.
1919 + All other licensing and usage conditions are those of the PHP Group.
1923 +/* $Id: apc_cache.h,v 3.45 2007/03/22 16:03:59 gopalv Exp $ */
1925 +#ifndef APC_CACHE_H
1926 +#define APC_CACHE_H
1929 + * This module defines the shared memory file cache. Basically all of the
1930 + * logic for storing and retrieving cache entries lives here.
1934 +#include "apc_compile.h"
1936 +#define APC_CACHE_ENTRY_FILE 1
1937 +#define APC_CACHE_ENTRY_USER 2
1939 +#define APC_CACHE_KEY_FILE 1
1940 +#define APC_CACHE_KEY_USER 2
1941 +#define APC_CACHE_KEY_FPFILE 3
1943 +/* {{{ struct definition: apc_cache_key_t */
1944 +#define T apc_cache_t*
1945 +typedef struct apc_cache_t apc_cache_t; /* opaque cache type */
1947 +typedef union _apc_cache_key_data_t {
1949 + dev_t device; /* the filesystem device */
1950 + ino_t inode; /* the filesystem inode */
1953 + const char *identifier;
1954 + int identifier_len;
1957 + const char *fullpath;
1960 +} apc_cache_key_data_t;
1962 +typedef struct apc_cache_key_t apc_cache_key_t;
1963 +struct apc_cache_key_t {
1964 + apc_cache_key_data_t data;
1965 + time_t mtime; /* the mtime of this cached entry */
1966 + unsigned char type;
1970 +/* {{{ struct definition: apc_cache_entry_t */
1971 +typedef union _apc_cache_entry_value_t {
1973 + char *filename; /* absolute path to source file */
1974 + zend_op_array* op_array; /* op_array allocated in shared memory */
1975 + apc_function_t* functions; /* array of apc_function_t's */
1976 + apc_class_t* classes; /* array of apc_class_t's */
1984 +} apc_cache_entry_value_t;
1986 +typedef struct apc_cache_entry_t apc_cache_entry_t;
1987 +struct apc_cache_entry_t {
1988 + apc_cache_entry_value_t data;
1989 + unsigned char type;
1990 + unsigned char autofiltered;
1991 + unsigned char local;
1998 + * apc_cache_create creates the shared memory compiler cache. This function
1999 + * should be called just once (ideally in the web server parent process, e.g.
2000 + * in apache), otherwise you will end up with multiple caches (which won't
2001 + * necessarily break anything). Returns a pointer to the cache object.
2003 + * size_hint is a "hint" at the total number of source files that will be
2004 + * cached. It determines the physical size of the hash table. Passing 0 for
2005 + * this argument will use a reasonable default value.
2007 + * gc_ttl is the maximum time a cache entry may speed on the garbage
2008 + * collection list. This is basically a work around for the inherent
2009 + * unreliability of our reference counting mechanism (see apc_cache_release).
2011 + * ttl is the maximum time a cache entry can idle in a slot in case the slot
2012 + * is needed. This helps in cleaning up the cache and ensuring that entries
2013 + * hit frequently stay cached and ones not hit very often eventually disappear.
2015 +extern T apc_cache_create(int size_hint, int gc_ttl, int ttl);
2018 + * apc_cache_destroy releases any OS resources associated with a cache object.
2019 + * Under apache, this function can be safely called by the child processes
2022 +extern void apc_cache_destroy(T cache);
2025 + * apc_cache_clear empties a cache. This can safely be called at any time,
2026 + * even while other server processes are executing cached source files.
2028 +extern void apc_cache_clear(T cache);
2031 + * apc_cache_insert adds an entry to the cache, using a filename as a key.
2032 + * Internally, the filename is translated to a canonical representation, so
2033 + * that relative and absolute filenames will map to a single key. Returns
2034 + * non-zero if the file was successfully inserted, 0 otherwise. If 0 is
2035 + * returned, the caller must free the cache entry by calling
2036 + * apc_cache_free_entry (see below).
2038 + * key is the value created by apc_cache_make_file_key for file keys.
2040 + * value is a cache entry returned by apc_cache_make_entry (see below).
2042 +extern int apc_cache_insert(T cache, apc_cache_key_t key,
2043 + apc_cache_entry_t* value, time_t t);
2045 +extern int apc_cache_user_insert(T cache, apc_cache_key_t key,
2046 + apc_cache_entry_t* value, time_t t, int exclusive TSRMLS_DC);
2049 + * apc_cache_find searches for a cache entry by filename, and returns a
2050 + * pointer to the entry if found, NULL otherwise.
2052 + * key is a value created by apc_cache_make_file_key for file keys.
2054 +extern apc_cache_entry_t* apc_cache_find(T cache, apc_cache_key_t key, time_t t);
2057 + * apc_cache_user_find searches for a cache entry by its hashed identifier,
2058 + * and returns a pointer to the entry if found, NULL otherwise.
2061 +extern apc_cache_entry_t* apc_cache_user_find(T cache, char* strkey, int keylen, time_t t);
2064 + * apc_cache_user_delete finds an entry in the user cache and deletes it.
2066 +extern int apc_cache_user_delete(apc_cache_t* cache, char *strkey, int keylen);
2068 +/* apc_cach_fetch_zval takes a zval in the cache and reconstructs a runtime
2072 +zval* apc_cache_fetch_zval(zval* dst, const zval* src, apc_malloc_t allocate, apc_free_t deallocate);
2075 + * apc_cache_release decrements the reference count associated with a cache
2076 + * entry. Calling apc_cache_find automatically increments the reference count,
2077 + * and this function must be called post-execution to return the count to its
2078 + * original value. Failing to do so will prevent the entry from being
2079 + * garbage-collected.
2081 + * entry is the cache entry whose ref count you want to decrement.
2083 +extern void apc_cache_release(T cache, apc_cache_entry_t* entry);
2086 + * apc_cache_make_file_key creates a key object given a relative or absolute
2087 + * filename and an optional list of auxillary paths to search. include_path is
2088 + * searched if the filename cannot be found relative to the current working
2091 + * key points to caller-allocated storage (must not be null).
2093 + * filename is the path to the source file.
2095 + * include_path is a colon-separated list of directories to search.
2097 + * and finally we pass in the current request time so we can avoid
2098 + * caching files with a current mtime which tends to indicate that
2099 + * they are still being written to.
2101 +extern int apc_cache_make_file_key(apc_cache_key_t* key,
2102 + const char* filename,
2103 + const char* include_path,
2108 + * apc_cache_make_file_entry creates an apc_cache_entry_t object given a filename
2109 + * and the compilation results returned by the PHP compiler.
2111 +extern apc_cache_entry_t* apc_cache_make_file_entry(const char* filename,
2112 + zend_op_array* op_array,
2113 + apc_function_t* functions,
2114 + apc_class_t* classes);
2116 + * apc_cache_make_user_entry creates an apc_cache_entry_t object given an info string
2117 + * and the zval to be stored.
2119 +extern apc_cache_entry_t* apc_cache_make_user_entry(const char* info, int info_len, const zval *val, const unsigned int ttl);
2121 +extern int apc_cache_make_user_key(apc_cache_key_t* key, char* identifier, int identifier_len, const time_t t);
2124 + * Frees all memory associated with an object returned by apc_cache_make_entry
2127 +extern void apc_cache_free_entry(apc_cache_entry_t* entry);
2129 +/* {{{ struct definition: apc_cache_link_data_t */
2130 +typedef union _apc_cache_link_data_t {
2140 +} apc_cache_link_data_t;
2143 +/* {{{ struct definition: apc_cache_link_t */
2144 +typedef struct apc_cache_link_t apc_cache_link_t;
2145 +struct apc_cache_link_t {
2146 + apc_cache_link_data_t data;
2147 + unsigned char type;
2150 + time_t creation_time;
2151 + time_t deletion_time;
2152 + time_t access_time;
2155 + apc_cache_link_t* next;
2159 +/* {{{ struct definition: apc_cache_info_t */
2160 +typedef struct apc_cache_info_t apc_cache_info_t;
2161 +struct apc_cache_info_t {
2166 + apc_cache_link_t* list;
2167 + apc_cache_link_t* deleted_list;
2168 + time_t start_time;
2176 +extern apc_cache_info_t* apc_cache_info(T cache, zend_bool limited);
2177 +extern void apc_cache_free_info(apc_cache_info_t* info);
2178 +extern void apc_cache_expunge(apc_cache_t* cache, time_t t);
2179 +extern void apc_cache_unlock(apc_cache_t* cache);
2180 +extern zend_bool apc_cache_busy(apc_cache_t* cache);
2181 +extern zend_bool apc_cache_write_lock(apc_cache_t* cache);
2182 +extern void apc_cache_write_unlock(apc_cache_t* cache);
2185 + * Process local cache, which keeps a refcount hungry version of the slots
2186 + * for quick access without a lock - as long as the entry exists in local
2187 + * cache, the refcount of the shm version will be +1 more than required.
2188 + * It holds no data, only a shallow copy of apc_cache_entry.
2190 +typedef struct apc_local_cache_t apc_local_cache_t; /* process-local cache */
2192 +extern apc_local_cache_t* apc_local_cache_create(apc_cache_t *shmcache, int num_slots, int ttl);
2193 +extern apc_cache_entry_t* apc_local_cache_find(apc_local_cache_t* cache, apc_cache_key_t key, time_t t);
2194 +extern void apc_local_cache_destroy(apc_local_cache_t* cache);
2195 +extern void apc_local_cache_cleanup(apc_local_cache_t* cache);
2201 + * Local variables:
2203 + * c-basic-offset: 4
2205 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
2206 + * vim<600: expandtab sw=4 ts=4 sts=4
2208 diff -ruN php-5.1.6.old/ext/apc/apc_compile.c php-5.1.6/ext/APC/apc_compile.c
2209 --- php-5.1.6.old/ext/apc/apc_compile.c 1969-12-31 18:00:00.000000000 -0600
2210 +++ php-5.1.6/ext/apc/apc_compile.c 2007-04-02 18:05:30.000000000 -0500
2213 + +----------------------------------------------------------------------+
2215 + +----------------------------------------------------------------------+
2216 + | Copyright (c) 2006 The PHP Group |
2217 + +----------------------------------------------------------------------+
2218 + | This source file is subject to version 3.01 of the PHP license, |
2219 + | that is bundled with this package in the file LICENSE, and is |
2220 + | available through the world-wide-web at the following url: |
2221 + | http://www.php.net/license/3_01.txt. |
2222 + | If you did not receive a copy of the PHP license and are unable to |
2223 + | obtain it through the world-wide-web, please send a note to |
2224 + | license@php.net so we can mail you a copy immediately. |
2225 + +----------------------------------------------------------------------+
2226 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
2227 + | Rasmus Lerdorf <rasmus@php.net> |
2228 + | Arun C. Murthy <arunc@yahoo-inc.com> |
2229 + | Gopal Vijayaraghavan <gopalv@yahoo-inc.com> |
2230 + +----------------------------------------------------------------------+
2232 + This software was contributed to PHP by Community Connect Inc. in 2002
2233 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
2234 + Future revisions and derivatives of this source code must acknowledge
2235 + Community Connect Inc. as the original contributor of this module by
2236 + leaving this note intact in the source code.
2238 + All other licensing and usage conditions are those of the PHP Group.
2242 +/* $Id: apc_compile.c,v 3.85 2007/03/28 07:35:55 gopalv Exp $ */
2244 +#include "apc_compile.h"
2245 +#include "apc_globals.h"
2246 +#include "apc_zend.h"
2248 +typedef void* (*ht_copy_fun_t)(void*, void*, apc_malloc_t, apc_free_t);
2249 +typedef void (*ht_free_fun_t)(void*, apc_free_t);
2250 +typedef int (*ht_check_copy_fun_t)(Bucket*, va_list);
2252 +#ifdef ZEND_ENGINE_2
2253 +typedef void (*ht_fixup_fun_t)(Bucket*, zend_class_entry*, zend_class_entry*);
2256 +#define CHECK(p) { if ((p) == NULL) return NULL; }
2258 +/* {{{ internal function declarations */
2260 +static int is_derived_class(zend_op_array* op_array, const char* key, int key_size);
2262 +static zend_function* my_bitwise_copy_function(zend_function*, zend_function*, apc_malloc_t);
2265 + * The "copy" functions perform deep-copies on a particular data structure
2266 + * (passed as the second argument). They also optionally allocate space for
2267 + * the destination data structure if the first argument is null.
2269 +static zval** my_copy_zval_ptr(zval**, const zval**, apc_malloc_t, apc_free_t);
2270 +static zval* my_copy_zval(zval*, const zval*, apc_malloc_t, apc_free_t);
2271 +static znode* my_copy_znode(znode*, znode*, apc_malloc_t, apc_free_t);
2272 +static zend_op* my_copy_zend_op(zend_op*, zend_op*, apc_malloc_t, apc_free_t);
2273 +static zend_function* my_copy_function(zend_function*, zend_function*, apc_malloc_t, apc_free_t);
2274 +static zend_function_entry* my_copy_function_entry(zend_function_entry*, zend_function_entry*, apc_malloc_t, apc_free_t);
2275 +static zend_class_entry* my_copy_class_entry(zend_class_entry*, zend_class_entry*, apc_malloc_t, apc_free_t);
2276 +static HashTable* my_copy_hashtable_ex(HashTable*, HashTable*, ht_copy_fun_t, ht_free_fun_t, int, apc_malloc_t, apc_free_t, ht_check_copy_fun_t, ...);
2277 +#define my_copy_hashtable( dst, src, copy_fn, free_fn, holds_ptr, allocate, deallocate) \
2278 + my_copy_hashtable_ex(dst, src, copy_fn, free_fn, holds_ptr, allocate, deallocate, NULL)
2279 +static HashTable* my_copy_static_variables(zend_op_array* src, apc_malloc_t allocate, apc_free_t deallocate);
2280 +#ifdef ZEND_ENGINE_2
2281 +static zend_property_info* my_copy_property_info(zend_property_info* dst, zend_property_info* src, apc_malloc_t allocate, apc_free_t deallocate);
2282 +static zend_arg_info* my_copy_arg_info_array(zend_arg_info*, zend_arg_info*, uint, apc_malloc_t, apc_free_t);
2283 +static zend_arg_info* my_copy_arg_info(zend_arg_info*, zend_arg_info*, apc_malloc_t, apc_free_t);
2286 + * The "destroy" functions free the memory associated with a particular data
2287 + * structure but do not free the pointer to the data structure.
2289 + * my_destroy_zval() returns SUCCESS or FAILURE, FAILURE means that
2290 + * the zval* has other references elsewhere
2292 +static int my_destroy_zval(zval*, apc_free_t);
2293 +static void my_destroy_zval_ptr(zval**, apc_free_t);
2294 +static void my_destroy_zend_op(zend_op*, apc_free_t);
2295 +static void my_destroy_znode(znode*, apc_free_t);
2296 +static void my_destroy_function(zend_function*, apc_free_t);
2297 +static void my_destroy_function_entry(zend_function_entry*, apc_free_t);
2298 +static void my_destroy_class_entry(zend_class_entry*, apc_free_t);
2299 +static void my_destroy_hashtable(HashTable*, ht_free_fun_t, apc_free_t);
2300 +static void my_destroy_op_array(zend_op_array*, apc_free_t);
2301 +#ifdef ZEND_ENGINE_2
2302 +static void my_destroy_property_info(zend_property_info*, apc_free_t);
2303 +static void my_destroy_arg_info_array(zend_arg_info* src, uint, apc_free_t);
2304 +static void my_destroy_arg_info(zend_arg_info*, apc_free_t);
2308 + * The "free" functions work exactly like their "destroy" counterparts (see
2309 + * above) but also free the pointer to the data structure.
2311 +static void my_free_zval_ptr(zval**, apc_free_t);
2312 +static void my_free_function(zend_function*, apc_free_t);
2313 +static void my_free_hashtable(HashTable*, ht_free_fun_t, apc_free_t);
2314 +#ifdef ZEND_ENGINE_2
2315 +static void my_free_property_info(zend_property_info* src, apc_free_t);
2316 +static void my_free_arg_info_array(zend_arg_info*, uint, apc_free_t);
2317 +static void my_free_arg_info(zend_arg_info*, apc_free_t);
2321 + * The "fixup" functions need for ZEND_ENGINE_2
2323 +#ifdef ZEND_ENGINE_2
2324 +static void my_fixup_function( Bucket *p, zend_class_entry *src, zend_class_entry *dst );
2325 +static void my_fixup_hashtable( HashTable *ht, ht_fixup_fun_t fixup, zend_class_entry *src, zend_class_entry *dst );
2326 +/* my_fixup_function_for_execution is the same as my_fixup_function
2327 + * but named differently for clarity
2329 +#define my_fixup_function_for_execution my_fixup_function
2331 +#ifdef ZEND_ENGINE_2_2
2332 +static void my_fixup_property_info( Bucket *p, zend_class_entry *src, zend_class_entry *dst );
2333 +#define my_fixup_property_info_for_execution my_fixup_property_info
2339 + * These functions return "1" if the member/function is
2340 + * defined/overridden in the 'current' class and not inherited.
2342 +static int my_check_copy_function(Bucket* src, va_list args);
2343 +static int my_check_copy_default_property(Bucket* p, va_list args);
2344 +#ifdef ZEND_ENGINE_2
2345 +static int my_check_copy_property_info(Bucket* src, va_list args);
2346 +static int my_check_copy_static_member(Bucket* src, va_list args);
2351 +/* {{{ check_op_array_integrity */
2353 +static void check_op_array_integrity(zend_op_array* src)
2357 + /* These sorts of checks really aren't particularly effective, but they
2358 + * can provide a welcome sanity check when debugging. Just don't enable
2359 + * for production use! */
2361 + assert(src->refcount != NULL);
2362 + assert(src->opcodes != NULL);
2363 + assert(src->last > 0);
2365 + for (i = 0; i < src->last; i++) {
2366 + zend_op* op = &src->opcodes[i];
2367 + znode* nodes[] = { &op->result, &op->op1, &op->op2 };
2368 + for (j = 0; j < 3; j++) {
2369 + assert(nodes[j]->op_type == IS_CONST ||
2370 + nodes[j]->op_type == IS_VAR ||
2371 + nodes[j]->op_type == IS_TMP_VAR ||
2372 + nodes[j]->op_type == IS_UNUSED);
2374 + if (nodes[j]->op_type == IS_CONST) {
2375 + int type = nodes[j]->u.constant.type;
2376 + assert(type == IS_RESOURCE ||
2377 + type == IS_BOOL ||
2378 + type == IS_LONG ||
2379 + type == IS_DOUBLE ||
2380 + type == IS_NULL ||
2381 + type == IS_CONSTANT ||
2382 + type == IS_STRING ||
2383 + type == FLAG_IS_BC ||
2384 + type == IS_ARRAY ||
2385 + type == IS_CONSTANT_ARRAY ||
2386 + type == IS_OBJECT);
2394 +/* {{{ is_derived_class */
2395 +static int is_derived_class(zend_op_array* op_array, const char* key, int key_size)
2400 + * Scan the op_array for execution-time class declarations of derived
2401 + * classes. If we find one whose key matches our current class key, we
2402 + * know the current class is a derived class.
2404 + * This check is exceedingly inefficient (fortunately it only has to occur
2405 + * once, when the source file is first compiled and cached), but the
2406 + * compiler should save this information for us -- definitely a candidate
2407 + * for a Zend Engine patch.
2409 + * XXX checking for derived classes provides a minimal (albeit measurable)
2410 + * speed up. It may not be worth the added complexity -- considere
2411 + * removing this optimization.
2414 + for (i = 0; i < op_array->last; i++) {
2415 + zend_op* op = &op_array->opcodes[i];
2417 +#ifdef ZEND_ENGINE_2
2418 + if (op->opcode == ZEND_DECLARE_CLASS &&
2419 + op->extended_value == ZEND_DECLARE_INHERITED_CLASS)
2421 + if (op->opcode == ZEND_DECLARE_FUNCTION_OR_CLASS &&
2422 + op->extended_value == ZEND_DECLARE_INHERITED_CLASS)
2425 + if (op->op1.u.constant.value.str.len == key_size &&
2426 + !memcmp(op->op1.u.constant.value.str.val, key, key_size))
2437 +/* {{{ my_bitwise_copy_function */
2438 +static zend_function* my_bitwise_copy_function(zend_function* dst, zend_function* src, apc_malloc_t allocate)
2440 + assert(src != NULL);
2443 + CHECK(dst = (zend_function*) allocate(sizeof(src[0])));
2446 + /* We only need to do a bitwise copy */
2447 + memcpy(dst, src, sizeof(src[0]));
2453 +/* {{{ my_copy_zval_ptr */
2454 +static zval** my_copy_zval_ptr(zval** dst, const zval** src, apc_malloc_t allocate, apc_free_t deallocate)
2456 + int local_dst_alloc = 0;
2459 + assert(src != NULL);
2462 + CHECK(dst = (zval**) allocate(sizeof(zval*)));
2463 + local_dst_alloc = 1;
2466 + if(!(dst[0] = (zval*) allocate(sizeof(zval)))) {
2467 + if(local_dst_alloc) deallocate(dst);
2470 + dst_new = my_copy_zval(*dst, *src, allocate, deallocate);
2471 + if(dst_new != *dst) {
2476 + (*dst)->refcount = (*src)->refcount;
2477 + (*dst)->is_ref = (*src)->is_ref;
2483 +/* {{{ my_copy_zval */
2484 +static zval* my_copy_zval(zval* dst, const zval* src, apc_malloc_t allocate, apc_free_t deallocate)
2489 + assert(dst != NULL);
2490 + assert(src != NULL);
2492 + memcpy(dst, src, sizeof(src[0]));
2494 + switch (src->type & ~IS_CONSTANT_INDEX) {
2504 +#ifndef ZEND_ENGINE_2
2507 + if (src->value.str.val) {
2508 + CHECK(dst->value.str.val = apc_xmemcpy(src->value.str.val,
2509 + src->value.str.len+1,
2516 + if(APCG(copied_zvals)) {
2517 + if(zend_hash_index_find(APCG(copied_zvals), (ulong)src, (void**)&tmp) == SUCCESS) {
2518 + (*tmp)->refcount++;
2522 + zend_hash_index_update(APCG(copied_zvals), (ulong)src, (void**)&dst, sizeof(zval*), NULL);
2524 + /* fall through */
2526 + case IS_CONSTANT_ARRAY:
2528 + CHECK(dst->value.ht =
2529 + my_copy_hashtable(NULL,
2531 + (ht_copy_fun_t) my_copy_zval_ptr,
2532 + (ht_free_fun_t) my_free_zval_ptr,
2534 + allocate, deallocate));
2538 +#ifndef ZEND_ENGINE_2
2539 + CHECK(dst->value.obj.ce =
2540 + my_copy_class_entry(NULL, src->value.obj.ce, allocate, deallocate));
2542 + if(!(dst->value.obj.properties = my_copy_hashtable(NULL,
2543 + src->value.obj.properties,
2544 + (ht_copy_fun_t) my_copy_zval_ptr,
2545 + (ht_free_fun_t) my_free_zval_ptr,
2547 + allocate, deallocate))) {
2548 + my_destroy_class_entry(dst->value.obj.ce, deallocate);
2553 + dst->type = IS_NULL;
2565 +/* {{{ my_copy_znode */
2566 +static znode* my_copy_znode(znode* dst, znode* src, apc_malloc_t allocate, apc_free_t deallocate)
2568 + assert(dst != NULL);
2569 + assert(src != NULL);
2571 + memcpy(dst, src, sizeof(src[0]));
2574 + assert(dst ->op_type == IS_CONST ||
2575 + dst ->op_type == IS_VAR ||
2576 + dst ->op_type == IS_CV ||
2577 + dst ->op_type == IS_TMP_VAR ||
2578 + dst ->op_type == IS_UNUSED);
2580 + assert(dst ->op_type == IS_CONST ||
2581 + dst ->op_type == IS_VAR ||
2582 + dst ->op_type == IS_TMP_VAR ||
2583 + dst ->op_type == IS_UNUSED);
2586 + if (src->op_type == IS_CONST) {
2587 + if(!my_copy_zval(&dst->u.constant, &src->u.constant, allocate, deallocate)) {
2596 +/* {{{ my_copy_zend_op */
2597 +static zend_op* my_copy_zend_op(zend_op* dst, zend_op* src, apc_malloc_t allocate, apc_free_t deallocate)
2599 + assert(dst != NULL);
2600 + assert(src != NULL);
2602 + memcpy(dst, src, sizeof(src[0]));
2604 + if( my_copy_znode(&dst->result, &src->result, allocate, deallocate) == NULL
2605 + || my_copy_znode(&dst->op1, &src->op1, allocate, deallocate) == NULL
2606 + || my_copy_znode(&dst->op2, &src->op2, allocate, deallocate) == NULL)
2615 +/* {{{ my_copy_function */
2616 +static zend_function* my_copy_function(zend_function* dst, zend_function* src, apc_malloc_t allocate, apc_free_t deallocate)
2618 + int local_dst_alloc = 0;
2621 + assert(src != NULL);
2623 + if(!dst) local_dst_alloc = 1;
2624 + CHECK(dst = my_bitwise_copy_function(dst, src, allocate));
2626 + switch (src->type) {
2627 + case ZEND_INTERNAL_FUNCTION:
2628 + case ZEND_OVERLOADED_FUNCTION:
2629 + /* shallow copy because op_array is internal */
2630 + dst->op_array = src->op_array;
2633 + case ZEND_USER_FUNCTION:
2634 + case ZEND_EVAL_CODE:
2635 + if(!apc_copy_op_array(&dst->op_array,
2637 + allocate, deallocate TSRMLS_CC)) {
2638 + if(local_dst_alloc) deallocate(dst);
2646 +#ifdef ZEND_ENGINE_2
2648 + * op_array bitwise copying overwrites what ever you modified
2649 + * before apc_copy_op_array - which is why this code is outside
2650 + * my_bitwise_copy_function.
2653 + /* zend_do_inheritance will re-look this up, because the pointers
2654 + * in prototype are from a function table of another class. It just
2655 + * helps if that one is from EG(class_table).
2657 + dst->common.prototype = NULL;
2659 + /* once a method is marked as ZEND_ACC_IMPLEMENTED_ABSTRACT then you
2660 + * have to carry around a prototype. Thankfully zend_do_inheritance
2661 + * sets this properly as well
2663 + dst->common.fn_flags = src->common.fn_flags & (~ZEND_ACC_IMPLEMENTED_ABSTRACT);
2671 +/* {{{ my_copy_function_entry */
2672 +static zend_function_entry* my_copy_function_entry(zend_function_entry* dst, zend_function_entry* src, apc_malloc_t allocate, apc_free_t deallocate)
2674 + int local_dst_alloc = 0;
2675 + assert(src != NULL);
2678 + CHECK(dst = (zend_function_entry*) allocate(sizeof(src[0])));
2679 + local_dst_alloc = 1;
2682 + /* Start with a bitwise copy */
2683 + memcpy(dst, src, sizeof(src[0]));
2685 + dst->fname = NULL;
2686 +#ifdef ZEND_ENGINE_2
2687 + dst->arg_info = NULL;
2689 + dst->func_arg_types = NULL;
2693 + if(!(dst->fname = apc_xstrdup(src->fname, allocate))) {
2698 +#ifdef ZEND_ENGINE_2
2699 + if (src->arg_info) {
2700 + if(!(dst->arg_info = my_copy_arg_info_array(NULL,
2709 + if (src->func_arg_types) {
2710 + if(!(dst->func_arg_types = apc_xmemcpy(src->func_arg_types,
2711 + src->func_arg_types[0]+1,
2721 + if(dst->fname) deallocate(dst->fname);
2722 + if(local_dst_alloc) deallocate(dst);
2727 +#ifdef ZEND_ENGINE_2
2728 +/* {{{ my_copy_property_info */
2729 +static zend_property_info* my_copy_property_info(zend_property_info* dst, zend_property_info* src, apc_malloc_t allocate, apc_free_t deallocate)
2731 + int local_dst_alloc = 0;
2733 + assert(src != NULL);
2736 + CHECK(dst = (zend_property_info*) allocate(sizeof(*src)));
2737 + local_dst_alloc = 1;
2740 + /* Start with a bitwise copy */
2741 + memcpy(dst, src, sizeof(*src));
2744 +#if defined(ZEND_ENGINE_2) && PHP_MINOR_VERSION > 0
2745 + dst->doc_comment = NULL;
2749 + /* private members are stored inside property_info as a mangled
2750 + * string of the form:
2751 + * \0<classname>\0<membername>\0
2754 + apc_xmemcpy(src->name, src->name_length+1, allocate))) {
2759 +#if defined(ZEND_ENGINE_2) && PHP_MINOR_VERSION > 0
2760 + if (src->doc_comment) {
2761 + if( !(dst->doc_comment =
2762 + apc_xmemcpy(src->doc_comment, src->doc_comment_len+1, allocate))) {
2771 + if(dst->name) deallocate(dst->name);
2772 +#if defined(ZEND_ENGINE_2) && PHP_MINOR_VERSION > 0
2773 + if(dst->doc_comment) deallocate(dst->doc_comment);
2775 + if(local_dst_alloc) deallocate(dst);
2780 +/* {{{ my_copy_property_info_for_execution */
2781 +static zend_property_info* my_copy_property_info_for_execution(zend_property_info* dst, zend_property_info* src, apc_malloc_t allocate, apc_free_t deallocate)
2783 + int local_dst_alloc = 0;
2785 + assert(src != NULL);
2788 + CHECK(dst = (zend_property_info*) allocate(sizeof(*src)));
2789 + local_dst_alloc = 1;
2792 + /* We need only a shallow copy */
2793 + memcpy(dst, src, sizeof(*src));
2799 +/* {{{ my_copy_arg_info_array */
2800 +static zend_arg_info* my_copy_arg_info_array(zend_arg_info* dst, zend_arg_info* src, uint num_args, apc_malloc_t allocate, apc_free_t deallocate)
2802 + int local_dst_alloc = 0;
2807 + CHECK(dst = (zend_arg_info*) allocate(sizeof(*src)*num_args));
2808 + local_dst_alloc = 1;
2811 + /* Start with a bitwise copy */
2812 + memcpy(dst, src, sizeof(*src)*num_args);
2814 + for(i=0; i < num_args; i++) {
2815 + if(!(my_copy_arg_info( &dst[i], &src[i], allocate, deallocate))) {
2816 + if(i) my_destroy_arg_info_array(dst, i-1, deallocate);
2817 + if(local_dst_alloc) deallocate(dst);
2826 +/* {{{ my_copy_arg_info */
2827 +static zend_arg_info* my_copy_arg_info(zend_arg_info* dst, zend_arg_info* src, apc_malloc_t allocate, apc_free_t deallocate)
2829 + int local_dst_alloc = 0;
2831 + assert(src != NULL);
2834 + CHECK(dst = (zend_arg_info*) allocate(sizeof(*src)));
2835 + local_dst_alloc = 1;
2838 + /* Start with a bitwise copy */
2839 + memcpy(dst, src, sizeof(*src));
2842 + dst->class_name = NULL;
2846 + apc_xmemcpy(src->name, src->name_len+1, allocate))) {
2851 + if (src->class_name) {
2852 + if(!(dst->class_name =
2853 + apc_xmemcpy(src->class_name, src->class_name_len+1, allocate))) {
2861 + if(dst->name) deallocate(dst->name);
2862 + if(dst->class_name) deallocate(dst->name);
2863 + if(local_dst_alloc) deallocate(dst);
2869 +/* {{{ my_copy_class_entry */
2870 +static zend_class_entry* my_copy_class_entry(zend_class_entry* dst, zend_class_entry* src, apc_malloc_t allocate, apc_free_t deallocate)
2872 + int local_dst_alloc = 0;
2875 + assert(src != NULL);
2878 + CHECK(dst = (zend_class_entry*) allocate(sizeof(*src)));
2879 + local_dst_alloc = 1;
2882 + /* Start with a bitwise copy */
2883 + memcpy(dst, src, sizeof(*src));
2886 + dst->builtin_functions = NULL;
2887 + memset(&dst->function_table, 0, sizeof(dst->function_table));
2888 + memset(&dst->default_properties, 0, sizeof(dst->default_properties));
2889 +#ifndef ZEND_ENGINE_2
2890 + dst->refcount = NULL;
2892 + dst->static_members = NULL;
2893 + dst->doc_comment = NULL;
2894 + dst->filename = NULL;
2895 + memset(&dst->properties_info, 0, sizeof(dst->properties_info));
2896 + memset(&dst->constants_table, 0, sizeof(dst->constants_table));
2897 + memset(&dst->default_static_members, 0, sizeof(dst->default_static_members));
2901 + if(!(dst->name = apc_xstrdup(src->name, allocate))) {
2906 +#ifndef ZEND_ENGINE_2
2907 + if(!(dst->refcount = apc_xmemcpy(src->refcount,
2908 + sizeof(src->refcount[0]),
2914 + if(!(my_copy_hashtable_ex(&dst->function_table,
2915 + &src->function_table,
2916 + (ht_copy_fun_t) my_copy_function,
2917 + (ht_free_fun_t) my_free_function,
2919 + allocate, deallocate,
2920 + (ht_check_copy_fun_t) my_check_copy_function,
2925 +#ifdef ZEND_ENGINE_2
2927 + /* the interfaces are populated at runtime using ADD_INTERFACE */
2928 + dst->interfaces = NULL;
2930 + /* the current count includes inherited interfaces as well,
2931 + the real dynamic ones are the first <n> which are zero'd
2932 + out in zend_do_end_class_declaration */
2933 + for(i = 0 ; i < src->num_interfaces ; i++) {
2934 + if(src->interfaces[i])
2936 + dst->num_interfaces = i;
2941 + /* these will either be set inside my_fixup_hashtable or
2942 + * they will be copied out from parent inside zend_do_inheritance
2944 + dst->constructor = NULL;
2945 + dst->destructor = NULL;
2946 + dst->clone = NULL;
2947 + dst->__get = NULL;
2948 + dst->__set = NULL;
2949 + dst->__unset = NULL;
2950 + dst->__isset = NULL;
2951 + dst->__call = NULL;
2952 +#ifdef ZEND_ENGINE_2_2
2953 + dst->__tostring = NULL;
2956 + /* unset function proxies */
2957 + dst->serialize_func = NULL;
2958 + dst->unserialize_func = NULL;
2960 + my_fixup_hashtable(&dst->function_table, (ht_fixup_fun_t)my_fixup_function, src, dst);
2963 + if(!(my_copy_hashtable_ex(&dst->default_properties,
2964 + &src->default_properties,
2965 + (ht_copy_fun_t) my_copy_zval_ptr,
2966 + (ht_free_fun_t) my_free_zval_ptr,
2968 + allocate,deallocate,
2969 + (ht_check_copy_fun_t) my_check_copy_default_property,
2974 +#ifdef ZEND_ENGINE_2
2976 + if(!(my_copy_hashtable_ex(&dst->properties_info,
2977 + &src->properties_info,
2978 + (ht_copy_fun_t) my_copy_property_info,
2979 + (ht_free_fun_t) my_free_property_info,
2981 + allocate, deallocate,
2982 + (ht_check_copy_fun_t) my_check_copy_property_info,
2987 +#ifdef ZEND_ENGINE_2_2
2988 + /* php5.2 introduced a scope attribute for property info */
2989 + my_fixup_hashtable(&dst->properties_info, (ht_fixup_fun_t)my_fixup_property_info_for_execution, src, dst);
2992 + if(!my_copy_hashtable_ex(&dst->default_static_members,
2993 + &src->default_static_members,
2994 + (ht_copy_fun_t) my_copy_zval_ptr,
2995 + (ht_free_fun_t) my_free_zval_ptr,
2997 + allocate, deallocate,
2998 + (ht_check_copy_fun_t) my_check_copy_static_member,
3000 + &src->default_static_members)) {
3003 + if(src->static_members != &src->default_static_members)
3005 + if(!(dst->static_members = my_copy_hashtable_ex(NULL,
3006 + src->static_members,
3007 + (ht_copy_fun_t) my_copy_zval_ptr,
3008 + (ht_free_fun_t) my_free_zval_ptr,
3010 + allocate, deallocate,
3011 + (ht_check_copy_fun_t) my_check_copy_static_member,
3013 + src->static_members))) {
3019 + dst->static_members = &dst->default_static_members;
3022 + if(!(my_copy_hashtable(&dst->constants_table,
3023 + &src->constants_table,
3024 + (ht_copy_fun_t) my_copy_zval_ptr,
3025 + (ht_free_fun_t) my_free_zval_ptr,
3027 + allocate, deallocate))) {
3031 + if (src->doc_comment) {
3032 + if(!(dst->doc_comment =
3033 + apc_xmemcpy(src->doc_comment, src->doc_comment_len+1, allocate))) {
3039 + if (src->builtin_functions) {
3042 + for (n = 0; src->type == ZEND_INTERNAL_CLASS && src->builtin_functions[n].fname != NULL; n++) {}
3044 + if(!(dst->builtin_functions =
3045 + (zend_function_entry*)
3046 + allocate((n + 1) * sizeof(zend_function_entry)))) {
3051 + for (i = 0; i < n; i++) {
3052 + if(!my_copy_function_entry(&dst->builtin_functions[i],
3053 + &src->builtin_functions[i],
3054 + allocate, deallocate)) {
3057 + for(ii=i-1; i>=0; i--) my_destroy_function_entry(&dst->builtin_functions[ii], deallocate);
3061 + dst->builtin_functions[n].fname = NULL;
3064 +#ifdef ZEND_ENGINE_2
3065 + if (src->filename) {
3066 + if(!(dst->filename = apc_xstrdup(src->filename, allocate))) {
3076 + if(dst->name) deallocate(dst->name);
3077 +#ifdef ZEND_ENGINE_2
3078 + if(dst->doc_comment) deallocate(dst->doc_comment);
3079 + if(dst->filename) deallocate(dst->filename);
3081 + if(dst->refcount) deallocate(dst->refcount);
3084 + if(dst->builtin_functions) deallocate(dst->builtin_functions);
3085 + if(dst->function_table.arBuckets) my_destroy_hashtable(&dst->function_table, (ht_free_fun_t) my_free_function, deallocate);
3086 + if(dst->default_properties.arBuckets) my_destroy_hashtable(&dst->default_properties, (ht_free_fun_t) my_free_zval_ptr, deallocate);
3088 +#ifdef ZEND_ENGINE_2
3089 + if(dst->properties_info.arBuckets) my_destroy_hashtable(&dst->properties_info, (ht_free_fun_t) my_free_property_info, deallocate);
3090 + if(dst->default_static_members.arBuckets)
3092 + my_destroy_hashtable(&dst->default_static_members, (ht_free_fun_t) my_free_zval_ptr, deallocate);
3094 + if(dst->static_members && dst->static_members != &(dst->default_static_members))
3096 + my_destroy_hashtable(dst->static_members, (ht_free_fun_t) my_free_zval_ptr, deallocate);
3097 + deallocate(dst->static_members);
3099 + if(dst->constants_table.arBuckets) my_destroy_hashtable(&dst->constants_table, (ht_free_fun_t) my_free_zval_ptr, deallocate);
3101 + if(local_dst_alloc) deallocate(dst);
3107 +/* {{{ my_copy_hashtable */
3108 +static HashTable* my_copy_hashtable_ex(HashTable* dst,
3110 + ht_copy_fun_t copy_fn,
3111 + ht_free_fun_t free_fn,
3113 + apc_malloc_t allocate,
3114 + apc_free_t deallocate,
3115 + ht_check_copy_fun_t check_fn,
3118 + Bucket* curr = NULL;
3119 + Bucket* prev = NULL;
3120 + Bucket* newp = NULL;
3122 + int local_dst_alloc = 0;
3125 + assert(src != NULL);
3128 + CHECK(dst = (HashTable*) allocate(sizeof(src[0])));
3129 + local_dst_alloc = 1;
3132 + memcpy(dst, src, sizeof(src[0]));
3134 + /* allocate buckets for the new hashtable */
3135 + if(!(dst->arBuckets = allocate(dst->nTableSize * sizeof(Bucket*)))) {
3136 + if(local_dst_alloc) deallocate(dst);
3140 + memset(dst->arBuckets, 0, dst->nTableSize * sizeof(Bucket*));
3141 + dst->pInternalPointer = NULL;
3142 + dst->pListHead = NULL;
3144 + for (curr = src->pListHead; curr != NULL; curr = curr->pListNext) {
3145 + int n = curr->h % dst->nTableSize;
3149 + va_start(args, check_fn);
3151 + /* Call the check_fn to see if the current bucket
3152 + * needs to be copied out
3154 + if(!check_fn(curr, args)) {
3155 + dst->nNumOfElements--;
3162 + /* create a copy of the bucket 'curr' */
3164 + (Bucket*) apc_xmemcpy(curr,
3165 + sizeof(Bucket) + curr->nKeyLength - 1,
3170 + /* insert 'newp' into the linked list at its hashed index */
3171 + if (dst->arBuckets[n]) {
3172 + newp->pNext = dst->arBuckets[n];
3173 + newp->pLast = NULL;
3174 + newp->pNext->pLast = newp;
3177 + newp->pNext = newp->pLast = NULL;
3180 + dst->arBuckets[n] = newp;
3182 + /* copy the bucket data using our 'copy_fn' callback function */
3183 + if(!(newp->pData = copy_fn(NULL, curr->pData, allocate, deallocate))) {
3188 + memcpy(&newp->pDataPtr, newp->pData, sizeof(void*));
3191 + newp->pDataPtr = NULL;
3194 + /* insert 'newp' into the table-thread linked list */
3195 + newp->pListLast = prev;
3196 + newp->pListNext = NULL;
3199 + prev->pListNext = newp;
3203 + dst->pListHead = newp;
3210 + dst->pListTail = newp;
3215 + for(index = 0; index < dst->nTableSize; index++)
3217 + curr = dst->arBuckets[index];
3218 + while(curr != NULL)
3220 + Bucket * tmp = curr;
3221 + if(curr->pData && free_fn)
3223 + free_fn(curr->pData, deallocate);
3225 + curr = curr->pNext;
3229 + deallocate(dst->arBuckets);
3230 + if(local_dst_alloc) deallocate(dst);
3231 + else dst->arBuckets = NULL;
3237 +/* {{{ my_copy_static_variables */
3238 +static HashTable* my_copy_static_variables(zend_op_array* src, apc_malloc_t allocate, apc_free_t deallocate)
3240 + if (src->static_variables == NULL) {
3244 + return my_copy_hashtable(NULL,
3245 + src->static_variables,
3246 + (ht_copy_fun_t) my_copy_zval_ptr,
3247 + (ht_free_fun_t) my_free_zval_ptr,
3249 + allocate, deallocate);
3253 +/* {{{ apc_copy_zval */
3254 +zval* apc_copy_zval(zval* dst, const zval* src, apc_malloc_t allocate, apc_free_t deallocate)
3256 + int local_dst_alloc = 0;
3257 + assert(src != NULL);
3260 + CHECK(dst = (zval*) allocate(sizeof(zval)));
3261 + local_dst_alloc = 1;
3264 + dst = my_copy_zval(dst, src, allocate, deallocate);
3266 + if(local_dst_alloc) deallocate(dst);
3273 +#ifdef ZEND_ENGINE_2
3274 +/* {{{ apc_fixup_op_array_jumps */
3275 +static void apc_fixup_op_array_jumps(zend_op_array *dst, zend_op_array *src )
3279 + for (i=0; i < dst->last; ++i) {
3280 + zend_op *zo = &(dst->opcodes[i]);
3281 + /*convert opline number to jump address*/
3282 + switch (zo->opcode) {
3284 + /*Note: if src->opcodes != dst->opcodes then we need to the opline according to src*/
3285 + zo->op1.u.jmp_addr = dst->opcodes + (zo->op1.u.jmp_addr - src->opcodes);
3289 + case ZEND_JMPZ_EX:
3290 + case ZEND_JMPNZ_EX:
3291 + zo->op2.u.jmp_addr = dst->opcodes + (zo->op2.u.jmp_addr - src->opcodes);
3301 +/* {{{ apc_copy_op_array */
3302 +zend_op_array* apc_copy_op_array(zend_op_array* dst, zend_op_array* src, apc_malloc_t allocate, apc_free_t deallocate TSRMLS_DC)
3305 + int local_dst_alloc = 0;
3306 + apc_fileinfo_t fileinfo;
3307 + char canon_path[MAXPATHLEN];
3308 + char *fullpath = NULL;
3309 +#ifdef ZEND_ENGINE_2
3310 + apc_opflags_t * flags = NULL;
3313 + assert(src != NULL);
3316 + CHECK(dst = (zend_op_array*) allocate(sizeof(src[0])));
3317 + local_dst_alloc = 1;
3320 + if(APCG(apc_optimize_function)) {
3321 + APCG(apc_optimize_function)(src TSRMLS_CC);
3324 + /* start with a bitwise copy of the array */
3325 + memcpy(dst, src, sizeof(src[0]));
3327 + dst->function_name = NULL;
3328 + dst->filename = NULL;
3329 + dst->refcount = NULL;
3330 + dst->opcodes = NULL;
3331 + dst->brk_cont_array = NULL;
3332 + dst->static_variables = NULL;
3333 +#ifdef ZEND_ENGINE_2
3334 + dst->try_catch_array = NULL;
3335 + dst->arg_info = NULL;
3336 + dst->doc_comment = NULL;
3338 + dst->arg_types = NULL;
3340 +#ifdef ZEND_ENGINE_2_1
3344 + /* copy the arg types array (if set) */
3345 +#ifdef ZEND_ENGINE_2
3346 + if (src->arg_info) {
3347 + if(!(dst->arg_info = my_copy_arg_info_array(NULL,
3356 + if (src->arg_types) {
3357 + if(!(dst->arg_types = apc_xmemcpy(src->arg_types,
3358 + sizeof(src->arg_types[0]) * (src->arg_types[0]+1),
3365 + if (src->function_name) {
3366 + if(!(dst->function_name = apc_xstrdup(src->function_name, allocate))) {
3370 + if (src->filename) {
3371 + if(!(dst->filename = apc_xstrdup(src->filename, allocate))) {
3376 + if(!(dst->refcount = apc_xmemcpy(src->refcount,
3377 + sizeof(src->refcount[0]),
3382 + /* deep-copy the opcodes */
3383 + if(!(dst->opcodes = (zend_op*) allocate(sizeof(zend_op) * src->last))) {
3387 +#ifdef ZEND_ENGINE_2
3388 + if(APCG(reserved_offset) != -1) {
3389 + /* Insanity alert: the void* pointer is cast into an apc_opflags_t
3390 + * struct. apc_zend_init() checks to ensure that it fits in a void* */
3391 + flags = (apc_opflags_t*) & (dst->reserved[APCG(reserved_offset)]);
3392 + memset(flags, 0, sizeof(apc_opflags_t));
3393 + /* assert(sizeof(apc_opflags_t) < sizeof(dst->reserved)); */
3397 + for (i = 0; i < src->last; i++) {
3398 +#ifdef ZEND_ENGINE_2
3399 + zend_op *zo = &(src->opcodes[i]);
3400 + /* a lot of files are merely constant arrays with no jumps */
3401 + switch (zo->opcode) {
3405 + case ZEND_JMPZ_EX:
3406 + case ZEND_JMPNZ_EX:
3407 + if(flags != NULL) {
3408 + flags->has_jumps = 1;
3411 +#ifdef ZEND_ENGINE_2
3412 + /* auto_globals_jit was not in php-4.3.* */
3413 + case ZEND_FETCH_R:
3414 + case ZEND_FETCH_W:
3415 + case ZEND_FETCH_IS:
3416 + case ZEND_FETCH_FUNC_ARG:
3417 + if(PG(auto_globals_jit) && flags != NULL)
3419 + /* The fetch is only required if auto_globals_jit=1 */
3420 + if(zo->op2.u.EA.type == ZEND_FETCH_GLOBAL &&
3421 + zo->op1.op_type == IS_CONST &&
3422 + zo->op1.u.constant.type == IS_STRING) {
3423 + znode * varname = &zo->op1;
3424 + if (varname->u.constant.value.str.val[0] == '_') {
3425 +#define SET_IF_AUTOGLOBAL(member) \
3426 + if(!strcmp(varname->u.constant.value.str.val, #member)) \
3427 + flags->member = 1 /* no ';' here */
3428 + SET_IF_AUTOGLOBAL(_GET);
3429 + else SET_IF_AUTOGLOBAL(_POST);
3430 + else SET_IF_AUTOGLOBAL(_COOKIE);
3431 + else SET_IF_AUTOGLOBAL(_SERVER);
3432 + else SET_IF_AUTOGLOBAL(_ENV);
3433 + else SET_IF_AUTOGLOBAL(_FILES);
3434 + else SET_IF_AUTOGLOBAL(_REQUEST);
3435 + else if(zend_is_auto_global(
3436 + varname->u.constant.value.str.val,
3437 + varname->u.constant.value.str.len
3440 + flags->unknown_global = 1;
3447 + case ZEND_RECV_INIT:
3448 + if(zo->op2.op_type == IS_CONST &&
3449 + zo->op2.u.constant.type == IS_CONSTANT_ARRAY) {
3450 + if(flags != NULL) {
3451 + flags->deep_copy = 1;
3456 + if((zo->op1.op_type == IS_CONST &&
3457 + zo->op1.u.constant.type == IS_CONSTANT_ARRAY) ||
3458 + (zo->op2.op_type == IS_CONST &&
3459 + zo->op2.u.constant.type == IS_CONSTANT_ARRAY)) {
3460 + if(flags != NULL) {
3461 + flags->deep_copy = 1;
3467 + if(!(my_copy_zend_op(dst->opcodes+i, src->opcodes+i, allocate, deallocate))) {
3469 + for(ii = i-1; ii>=0; ii--) {
3470 + my_destroy_zend_op(dst->opcodes+ii, deallocate);
3474 +#ifdef ZEND_ENGINE_2
3475 +/* This code breaks apc's rule#1 - cache what you compile */
3476 + if(APCG(fpstat)==0) {
3477 + if((zo->opcode == ZEND_INCLUDE_OR_EVAL) &&
3478 + (zo->op1.op_type == IS_CONST && zo->op1.u.constant.type == IS_STRING)) {
3479 + /* constant includes */
3480 + if(!IS_ABSOLUTE_PATH(Z_STRVAL_P(&zo->op1.u.constant),len)) {
3481 + if (apc_search_paths(Z_STRVAL_P(&zo->op1.u.constant), PG(include_path), &fileinfo) == 0) {
3482 + if((IS_ABSOLUTE_PATH(fileinfo.fullpath, strlen(fileinfo.fullpath)) && (fullpath = fileinfo.fullpath))
3483 + || (fullpath = realpath(fileinfo.fullpath, canon_path))) {
3484 + /* is either an absolute path or it goes through a realpath() */
3485 + zend_op *dzo = &(dst->opcodes[i]);
3486 + deallocate(dzo->op1.u.constant.value.str.val);
3487 + dzo->op1.u.constant.value.str.len = strlen(fullpath);
3488 + dzo->op1.u.constant.value.str.val = apc_xstrdup(fullpath, allocate);
3497 +#ifdef ZEND_ENGINE_2
3498 + if(flags == NULL || flags->has_jumps) {
3499 + apc_fixup_op_array_jumps(dst,src);
3503 + /* copy the break-continue array */
3504 + if (src->brk_cont_array) {
3505 + if(!(dst->brk_cont_array =
3506 + apc_xmemcpy(src->brk_cont_array,
3507 + sizeof(src->brk_cont_array[0]) * src->last_brk_cont,
3509 + goto cleanup_opcodes;
3513 + /* copy the table of static variables */
3514 + if (src->static_variables) {
3515 + if(!(dst->static_variables = my_copy_static_variables(src, allocate, deallocate))) {
3516 + goto cleanup_opcodes;
3520 +#ifdef ZEND_ENGINE_2
3521 + if (src->try_catch_array) {
3522 + if(!(dst->try_catch_array =
3523 + apc_xmemcpy(src->try_catch_array,
3524 + sizeof(src->try_catch_array[0]) * src->last_try_catch,
3526 + goto cleanup_opcodes;
3531 +#ifdef ZEND_ENGINE_2_1 /* PHP 5.1 */
3533 + if(!(dst->vars = apc_xmemcpy(src->vars,
3534 + sizeof(src->vars[0]) * src->last_var,
3536 + goto cleanup_opcodes;
3539 + for(i = 0; i < src->last_var; i++) dst->vars[i].name = NULL;
3541 + for(i = 0; i < src->last_var; i++) {
3542 + if(!(dst->vars[i].name = apc_xmemcpy(src->vars[i].name,
3543 + src->vars[i].name_len + 1,
3545 + dst->last_var = i;
3546 + goto cleanup_opcodes;
3552 +#ifdef ZEND_ENGINE_2
3553 + if (src->doc_comment) {
3554 + if (!(dst->doc_comment
3555 + = apc_xmemcpy(src->doc_comment, src->doc_comment_len+1, allocate))) {
3556 + goto cleanup_opcodes;
3564 + if(dst->opcodes) {
3565 + for(i=0; i < src->last; i++) my_destroy_zend_op(dst->opcodes+i, deallocate);
3568 + if(dst->function_name) deallocate(dst->function_name);
3569 + if(dst->refcount) deallocate(dst->refcount);
3570 + if(dst->filename) deallocate(dst->filename);
3571 +#ifdef ZEND_ENGINE_2
3572 + if(dst->arg_info) my_free_arg_info_array(dst->arg_info, dst->num_args, deallocate);
3573 + if(dst->try_catch_array) deallocate(dst->try_catch_array);
3574 + if(dst->doc_comment) deallocate(dst->doc_comment);
3576 + if(dst->arg_types) deallocate(dst->arg_types);
3578 + if(dst->opcodes) deallocate(dst->opcodes);
3579 + if(dst->brk_cont_array) deallocate(dst->brk_cont_array);
3580 + if(dst->static_variables) my_free_hashtable(dst->static_variables, (ht_free_fun_t)my_free_zval_ptr, (apc_free_t)deallocate);
3581 +#ifdef ZEND_ENGINE_2_1
3583 + for(i=0; i < dst->last_var; i++) {
3584 + if(dst->vars[i].name) deallocate(dst->vars[i].name);
3586 + deallocate(dst->vars);
3589 + if(local_dst_alloc) deallocate(dst);
3594 +/* {{{ apc_copy_new_functions */
3595 +apc_function_t* apc_copy_new_functions(int old_count, apc_malloc_t allocate, apc_free_t deallocate TSRMLS_DC)
3597 + apc_function_t* array;
3598 + int new_count; /* number of new functions in table */
3601 + new_count = zend_hash_num_elements(CG(function_table)) - old_count;
3602 + assert(new_count >= 0);
3606 + allocate(sizeof(apc_function_t) * (new_count+1)));
3608 + if (new_count == 0) {
3609 + array[0].function = NULL;
3613 + /* Skip the first `old_count` functions in the table */
3614 + zend_hash_internal_pointer_reset(CG(function_table));
3615 + for (i = 0; i < old_count; i++) {
3616 + zend_hash_move_forward(CG(function_table));
3619 + /* Add the next `new_count` functions to our array */
3620 + for (i = 0; i < new_count; i++) {
3623 + zend_function* fun;
3625 + zend_hash_get_current_key_ex(CG(function_table),
3632 + zend_hash_get_current_data(CG(function_table), (void**) &fun);
3634 + if(!(array[i].name = apc_xmemcpy(key, (int) key_size, allocate))) {
3636 + for(ii=i-1; ii>=0; ii--) {
3637 + deallocate(array[ii].name);
3638 + my_free_function(array[ii].function, deallocate);
3640 + deallocate(array);
3643 + array[i].name_len = (int) key_size-1;
3644 + if(!(array[i].function = my_copy_function(NULL, fun, allocate, deallocate))) {
3646 + deallocate(array[i].name);
3647 + for(ii=i-1; ii>=0; ii--) {
3648 + deallocate(array[ii].name);
3649 + my_free_function(array[ii].function, deallocate);
3651 + deallocate(array);
3654 + zend_hash_move_forward(CG(function_table));
3657 + array[i].function = NULL;
3662 +/* {{{ apc_copy_new_classes */
3663 +apc_class_t* apc_copy_new_classes(zend_op_array* op_array, int old_count, apc_malloc_t allocate, apc_free_t deallocate TSRMLS_DC)
3665 + apc_class_t* array;
3666 + int new_count; /* number of new classes in table */
3669 + new_count = zend_hash_num_elements(CG(class_table)) - old_count;
3670 + assert(new_count >= 0);
3674 + allocate(sizeof(apc_class_t)*(new_count+1)));
3676 + if (new_count == 0) {
3677 + array[0].class_entry = NULL;
3681 + /* Skip the first `old_count` classes in the table */
3682 + zend_hash_internal_pointer_reset(CG(class_table));
3683 + for (i = 0; i < old_count; i++) {
3684 + zend_hash_move_forward(CG(class_table));
3687 + /* Add the next `new_count` classes to our array */
3688 + for (i = 0; i < new_count; i++) {
3691 + zend_class_entry* elem = NULL;
3693 + array[i].class_entry = NULL;
3695 + zend_hash_get_current_key_ex(CG(class_table),
3702 + zend_hash_get_current_data(CG(class_table), (void**) &elem);
3705 +#ifdef ZEND_ENGINE_2
3706 + elem = *((zend_class_entry**)elem);
3709 + if(!(array[i].name = apc_xmemcpy(key, (int) key_size, allocate))) {
3712 + for(ii=i-1; ii>=0; ii--) {
3713 + deallocate(array[ii].name);
3714 + my_destroy_class_entry(array[ii].class_entry, deallocate);
3715 + deallocate(array[ii].class_entry);
3717 + deallocate(array);
3720 + array[i].name_len = (int) key_size-1;
3721 + if(!(array[i].class_entry = my_copy_class_entry(NULL, elem, allocate, deallocate))) {
3724 + deallocate(array[i].name);
3725 + for(ii=i-1; ii>=0; ii--) {
3726 + deallocate(array[ii].name);
3727 + my_destroy_class_entry(array[ii].class_entry, deallocate);
3728 + deallocate(array[ii].class_entry);
3730 + deallocate(array);
3735 + * If the class has a pointer to its parent class, save the parent
3736 + * name so that we can enable compile-time inheritance when we reload
3737 + * the child class; otherwise, set the parent name to null and scan
3738 + * the op_array to determine if this class inherits from some base
3739 + * class at execution-time.
3742 + if (elem->parent) {
3743 + if(!(array[i].parent_name =
3744 + apc_xstrdup(elem->parent->name, allocate))) {
3747 + for(ii=i; ii>=0; ii--) {
3748 + deallocate(array[ii].name);
3749 + my_destroy_class_entry(array[ii].class_entry, deallocate);
3750 + deallocate(array[ii].class_entry);
3751 + if(ii==i) continue;
3752 + if(array[ii].parent_name) deallocate(array[ii].parent_name);
3754 + deallocate(array);
3757 + array[i].is_derived = 1;
3760 + array[i].parent_name = NULL;
3761 + array[i].is_derived = is_derived_class(op_array, key, key_size);
3764 + zend_hash_move_forward(CG(class_table));
3767 + array[i].class_entry = NULL;
3772 +/* {{{ my_destroy_zval_ptr */
3773 +static void my_destroy_zval_ptr(zval** src, apc_free_t deallocate)
3775 + assert(src != NULL);
3776 + if(my_destroy_zval(src[0], deallocate) == SUCCESS) {
3777 + deallocate(src[0]);
3782 +/* {{{ my_destroy_zval */
3783 +static int my_destroy_zval(zval* src, apc_free_t deallocate)
3788 + switch (src->type & ~IS_CONSTANT_INDEX) {
3798 +#ifndef ZEND_ENGINE_2
3801 + deallocate(src->value.str.val);
3806 + /* Maintain a list of zvals we've copied to properly handle recursive structures */
3807 + if(APCG(copied_zvals)) {
3808 + if(zend_hash_index_find(APCG(copied_zvals), (ulong)src, (void**)&tmp) == SUCCESS) {
3809 + (*tmp)->refcount--;
3812 + zend_hash_index_update(APCG(copied_zvals), (ulong)src, (void**)&src, sizeof(zval*), NULL);
3814 + /* fall through */
3816 + case IS_CONSTANT_ARRAY:
3817 + my_free_hashtable(src->value.ht,
3818 + (ht_free_fun_t) my_free_zval_ptr,
3823 +#ifndef ZEND_ENGINE_2
3824 + my_destroy_class_entry(src->value.obj.ce, deallocate);
3825 + deallocate(src->value.obj.ce);
3826 + my_free_hashtable(src->value.obj.properties,
3827 + (ht_free_fun_t) my_free_zval_ptr,
3840 +/* {{{ my_destroy_znode */
3841 +static void my_destroy_znode(znode* src, apc_free_t deallocate)
3843 + if (src->op_type == IS_CONST) {
3844 + my_destroy_zval(&src->u.constant, deallocate);
3849 +/* {{{ my_destroy_zend_op */
3850 +static void my_destroy_zend_op(zend_op* src, apc_free_t deallocate)
3852 + my_destroy_znode(&src->result, deallocate);
3853 + my_destroy_znode(&src->op1, deallocate);
3854 + my_destroy_znode(&src->op2, deallocate);
3858 +/* {{{ my_destroy_function */
3859 +static void my_destroy_function(zend_function* src, apc_free_t deallocate)
3861 + assert(src != NULL);
3863 + switch (src->type) {
3864 + case ZEND_INTERNAL_FUNCTION:
3865 + case ZEND_OVERLOADED_FUNCTION:
3868 + case ZEND_USER_FUNCTION:
3869 + case ZEND_EVAL_CODE:
3870 + my_destroy_op_array(&src->op_array, deallocate);
3879 +/* {{{ my_destroy_function_entry */
3880 +static void my_destroy_function_entry(zend_function_entry* src, apc_free_t deallocate)
3882 + assert(src != NULL);
3884 + deallocate(src->fname);
3885 +#ifdef ZEND_ENGINE_2
3886 + if (src->arg_info) {
3887 + my_free_arg_info_array(src->arg_info, src->num_args, deallocate);
3890 + if (src->func_arg_types) {
3891 + deallocate(src->func_arg_types);
3897 +#ifdef ZEND_ENGINE_2
3898 +/* {{{ my_destroy_property_info*/
3899 +static void my_destroy_property_info(zend_property_info* src, apc_free_t deallocate)
3901 + assert(src != NULL);
3903 + deallocate(src->name);
3904 +#if defined(ZEND_ENGINE_2) && PHP_MINOR_VERSION > 0
3905 + if(src->doc_comment) deallocate(src->doc_comment);
3910 +/* {{{ my_destroy_arg_info_array */
3911 +static void my_destroy_arg_info_array(zend_arg_info* src, uint num_args, apc_free_t deallocate)
3915 + assert(src != NULL);
3917 + for(i=0; i < num_args; i++) {
3918 + my_destroy_arg_info(&src[i], deallocate);
3923 +/* {{{ my_destroy_arg_info */
3924 +static void my_destroy_arg_info(zend_arg_info* src, apc_free_t deallocate)
3926 + assert(src != NULL);
3928 + deallocate(src->name);
3929 + deallocate(src->class_name);
3934 +/* {{{ my_destroy_class_entry */
3935 +static void my_destroy_class_entry(zend_class_entry* src, apc_free_t deallocate)
3939 + assert(src != NULL);
3941 + deallocate(src->name);
3942 +#ifndef ZEND_ENGINE_2
3943 + deallocate(src->refcount);
3945 + if(src->doc_comment) deallocate(src->doc_comment);
3946 + if(src->filename) deallocate(src->filename);
3949 + my_destroy_hashtable(&src->function_table,
3950 + (ht_free_fun_t) my_free_function,
3953 + my_destroy_hashtable(&src->default_properties,
3954 + (ht_free_fun_t) my_free_zval_ptr,
3957 +#ifdef ZEND_ENGINE_2
3958 + my_destroy_hashtable(&src->properties_info,
3959 + (ht_free_fun_t) my_free_property_info,
3961 + if(src->static_members)
3963 + my_destroy_hashtable(src->static_members,
3964 + (ht_free_fun_t) my_free_zval_ptr,
3966 + if(src->static_members != &(src->default_static_members))
3968 + deallocate(src->static_members);
3972 + my_destroy_hashtable(&src->constants_table,
3973 + (ht_free_fun_t) my_free_zval_ptr,
3977 + if (src->builtin_functions) {
3978 + for (i = 0; src->builtin_functions[i].fname != NULL; i++) {
3979 + my_destroy_function_entry(&src->builtin_functions[i], deallocate);
3981 + deallocate(src->builtin_functions);
3986 +/* {{{ my_destroy_hashtable */
3987 +static void my_destroy_hashtable(HashTable* src, ht_free_fun_t free_fn, apc_free_t deallocate)
3991 + assert(src != NULL);
3993 + for (i = 0; i < src->nTableSize; i++) {
3994 + Bucket* p = src->arBuckets[i];
3995 + while (p != NULL) {
3998 + free_fn(q->pData, deallocate);
4003 + deallocate(src->arBuckets);
4007 +/* {{{ my_destroy_op_array */
4008 +static void my_destroy_op_array(zend_op_array* src, apc_free_t deallocate)
4012 + assert(src != NULL);
4014 +#ifdef ZEND_ENGINE_2
4015 + if (src->arg_info) {
4016 + my_free_arg_info_array(src->arg_info, src->num_args, deallocate);
4019 + if (src->arg_types) {
4020 + deallocate(src->arg_types);
4024 + deallocate(src->function_name);
4025 + deallocate(src->filename);
4026 + deallocate(src->refcount);
4028 + for (i = 0; i < src->last; i++) {
4029 + my_destroy_zend_op(src->opcodes + i, deallocate);
4031 + deallocate(src->opcodes);
4033 + if (src->brk_cont_array) {
4034 + deallocate(src->brk_cont_array);
4037 + if (src->static_variables) {
4038 + my_free_hashtable(src->static_variables,
4039 + (ht_free_fun_t) my_free_zval_ptr,
4043 +#ifdef ZEND_ENGINE_2_1
4045 + for(i=0; i < src->last_var; i++) {
4046 + if(src->vars[i].name) deallocate(src->vars[i].name);
4048 + deallocate(src->vars);
4051 +#ifdef ZEND_ENGINE_2
4052 + if(src->try_catch_array) {
4053 + deallocate(src->try_catch_array);
4055 + if (src->doc_comment) {
4056 + deallocate(src->doc_comment);
4062 +/* {{{ my_free_zval_ptr */
4063 +static void my_free_zval_ptr(zval** src, apc_free_t deallocate)
4065 + my_destroy_zval_ptr(src, deallocate);
4070 +#ifdef ZEND_ENGINE_2
4071 +/* {{{ my_free_property_info */
4072 +static void my_free_property_info(zend_property_info* src, apc_free_t deallocate)
4074 + my_destroy_property_info(src, deallocate);
4079 +/* {{{ my_free_arg_info_array */
4080 +static void my_free_arg_info_array(zend_arg_info* src, uint num_args, apc_free_t deallocate)
4082 + my_destroy_arg_info_array(src, num_args, deallocate);
4087 +/* {{{ my_free_arg_info */
4088 +static void my_free_arg_info(zend_arg_info* src, apc_free_t deallocate)
4090 + my_destroy_arg_info(src, deallocate);
4096 +/* {{{ my_free_function */
4097 +static void my_free_function(zend_function* src, apc_free_t deallocate)
4099 + my_destroy_function(src, deallocate);
4104 +/* {{{ my_free_hashtable */
4105 +static void my_free_hashtable(HashTable* src, ht_free_fun_t free_fn, apc_free_t deallocate)
4107 + my_destroy_hashtable(src, free_fn, deallocate);
4112 +/* {{{ apc_free_op_array */
4113 +void apc_free_op_array(zend_op_array* src, apc_free_t deallocate)
4115 + if (src != NULL) {
4116 + my_destroy_op_array(src, deallocate);
4122 +/* {{{ apc_free_functions */
4123 +void apc_free_functions(apc_function_t* src, apc_free_t deallocate)
4127 + if (src != NULL) {
4128 + for (i = 0; src[i].function != NULL; i++) {
4129 + deallocate(src[i].name);
4130 + my_destroy_function(src[i].function, deallocate);
4131 + deallocate(src[i].function);
4138 +/* {{{ apc_free_classes */
4139 +void apc_free_classes(apc_class_t* src, apc_free_t deallocate)
4143 + if (src != NULL) {
4144 + for (i = 0; src[i].class_entry != NULL; i++) {
4145 + deallocate(src[i].name);
4146 + deallocate(src[i].parent_name);
4147 + my_destroy_class_entry(src[i].class_entry, deallocate);
4148 + deallocate(src[i].class_entry);
4155 +/* {{{ apc_free_zval */
4156 +void apc_free_zval(zval* src, apc_free_t deallocate)
4158 + if (src != NULL) {
4159 + if(my_destroy_zval(src, deallocate) == SUCCESS) {
4167 +/* Used only by my_prepare_op_array_for_execution */
4168 +#define APC_PREPARE_FETCH_GLOBAL_FOR_EXECUTION() \
4169 + /* The fetch is only required if auto_globals_jit=1 */ \
4170 + if(zo->op2.u.EA.type == ZEND_FETCH_GLOBAL && \
4171 + zo->op1.op_type == IS_CONST && \
4172 + zo->op1.u.constant.type == IS_STRING && \
4173 + zo->op1.u.constant.value.str.val[0] == '_') { \
4175 + znode* varname = &zo->op1; \
4176 + (void)zend_is_auto_global(varname->u.constant.value.str.val, \
4177 + varname->u.constant.value.str.len \
4181 +/* {{{ my_prepare_op_array_for_execution */
4182 +static int my_prepare_op_array_for_execution(zend_op_array* dst, zend_op_array* src TSRMLS_DC)
4184 + /* combine my_fetch_global_vars and my_copy_data_exceptions.
4185 + * - Pre-fetch superglobals which would've been pre-fetched in parse phase.
4186 + * - If the opcode stream contain mutable data, ensure a copy.
4187 + * - Fixup array jumps in the same loop.
4192 +#ifdef ZEND_ENGINE_2
4193 + apc_opflags_t * flags = APCG(reserved_offset) != -1 ?
4194 + (apc_opflags_t*) & (src->reserved[APCG(reserved_offset)]) : NULL;
4195 + int needcopy = flags ? flags->deep_copy : 1;
4196 + /* auto_globals_jit was not in php4 */
4197 + int do_prepare_fetch_global = PG(auto_globals_jit) && (flags == NULL || flags->unknown_global);
4199 +#define FETCH_AUTOGLOBAL(member) do { \
4200 + if(flags && flags->member == 1) { \
4201 + zend_is_auto_global(#member,\
4202 + (sizeof(#member) - 1)\
4207 + FETCH_AUTOGLOBAL(_GET);
4208 + FETCH_AUTOGLOBAL(_POST);
4209 + FETCH_AUTOGLOBAL(_COOKIE);
4210 + FETCH_AUTOGLOBAL(_SERVER);
4211 + FETCH_AUTOGLOBAL(_ENV);
4212 + FETCH_AUTOGLOBAL(_FILES);
4213 + FETCH_AUTOGLOBAL(_REQUEST);
4217 + int do_prepare_fetch_global = 0;
4220 + for(j = 0; j < src->last; j++) {
4221 + zo = &src->opcodes[j];
4223 + if( ((zo->op1.op_type == IS_CONST &&
4224 + zo->op1.u.constant.type == IS_CONSTANT_ARRAY)) ||
4225 + ((zo->op2.op_type == IS_CONST &&
4226 + zo->op2.u.constant.type == IS_CONSTANT_ARRAY))) {
4234 + dst->opcodes = (zend_op*) apc_xmemcpy(src->opcodes,
4235 + sizeof(zend_op) * src->last,
4237 + zo = src->opcodes;
4238 + dzo = dst->opcodes;
4241 + if( ((zo->op1.op_type == IS_CONST &&
4242 + zo->op1.u.constant.type == IS_CONSTANT_ARRAY)) ||
4243 + ((zo->op2.op_type == IS_CONST &&
4244 + zo->op2.u.constant.type == IS_CONSTANT_ARRAY))) {
4246 + if(!(my_copy_zend_op(dzo, zo, apc_php_malloc, apc_php_free))) {
4247 + assert(0); /* emalloc failed or a bad constant array */
4251 +#ifdef ZEND_ENGINE_2
4252 + switch(zo->opcode) {
4254 + dzo->op1.u.jmp_addr = dst->opcodes +
4255 + (zo->op1.u.jmp_addr - src->opcodes);
4259 + case ZEND_JMPZ_EX:
4260 + case ZEND_JMPNZ_EX:
4261 + dzo->op2.u.jmp_addr = dst->opcodes +
4262 + (zo->op2.u.jmp_addr - src->opcodes);
4264 + case ZEND_FETCH_R:
4265 + case ZEND_FETCH_W:
4266 + case ZEND_FETCH_IS:
4267 + case ZEND_FETCH_FUNC_ARG:
4268 + if(do_prepare_fetch_global)
4270 + APC_PREPARE_FETCH_GLOBAL_FOR_EXECUTION();
4281 +#ifdef ZEND_ENGINE_2
4282 + } else { /* !needcopy */
4283 + /* The fetch is only required if auto_globals_jit=1 */
4284 + if(do_prepare_fetch_global)
4286 + zo = src->opcodes;
4289 + if(zo->opcode == ZEND_FETCH_R ||
4290 + zo->opcode == ZEND_FETCH_W ||
4291 + zo->opcode == ZEND_FETCH_IS ||
4292 + zo->opcode == ZEND_FETCH_FUNC_ARG
4294 + APC_PREPARE_FETCH_GLOBAL_FOR_EXECUTION();
4307 +/* {{{ apc_copy_op_array_for_execution */
4308 +zend_op_array* apc_copy_op_array_for_execution(zend_op_array* dst, zend_op_array* src TSRMLS_DC)
4311 + dst = (zend_op_array*) emalloc(sizeof(src[0]));
4313 + memcpy(dst, src, sizeof(src[0]));
4314 + dst->static_variables = my_copy_static_variables(src, apc_php_malloc, apc_php_free);
4316 + dst->refcount = apc_xmemcpy(src->refcount,
4317 + sizeof(src->refcount[0]),
4320 + my_prepare_op_array_for_execution(dst,src TSRMLS_CC);
4326 +/* {{{ apc_copy_function_for_execution */
4327 +zend_function* apc_copy_function_for_execution(zend_function* src)
4329 + zend_function* dst;
4332 + dst = (zend_function*) emalloc(sizeof(src[0]));
4333 + memcpy(dst, src, sizeof(src[0]));
4334 + apc_copy_op_array_for_execution(&(dst->op_array), &(src->op_array) TSRMLS_CC);
4339 +/* {{{ apc_copy_function_for_execution_ex */
4340 +zend_function* apc_copy_function_for_execution_ex(void *dummy, zend_function* src, apc_malloc_t allocate, apc_free_t deallocate)
4342 + if(src->type==ZEND_INTERNAL_FUNCTION || src->type==ZEND_OVERLOADED_FUNCTION) return src;
4343 + return apc_copy_function_for_execution(src);
4347 +/* {{{ apc_copy_class_entry_for_execution */
4348 +zend_class_entry* apc_copy_class_entry_for_execution(zend_class_entry* src, int is_derived)
4350 + zend_class_entry* dst = (zend_class_entry*) emalloc(sizeof(src[0]));
4351 + memcpy(dst, src, sizeof(src[0]));
4353 +#ifdef ZEND_ENGINE_2
4354 + if(src->num_interfaces)
4356 + /* These are slots to be populated later by ADD_INTERFACE insns */
4357 + dst->interfaces = apc_php_malloc(
4358 + sizeof(zend_class_entry*) * src->num_interfaces);
4359 + memset(dst->interfaces, 0,
4360 + sizeof(zend_class_entry*) * src->num_interfaces);
4364 + /* assert(dst->interfaces == NULL); */
4368 +#ifndef ZEND_ENGINE_2
4369 + dst->refcount = apc_xmemcpy(src->refcount,
4370 + sizeof(src->refcount[0]),
4374 + /* Deep-copy the class properties, because they will be modified */
4376 + my_copy_hashtable(&dst->default_properties,
4377 + &src->default_properties,
4378 + (ht_copy_fun_t) my_copy_zval_ptr,
4379 + (ht_free_fun_t) my_free_zval_ptr,
4381 + apc_php_malloc, apc_php_free);
4383 + /* For derived classes, we must also copy the function hashtable (although
4384 + * we can merely bitwise copy the functions it contains) */
4386 + my_copy_hashtable(&dst->function_table,
4387 + &src->function_table,
4388 + (ht_copy_fun_t) apc_copy_function_for_execution_ex,
4391 + apc_php_malloc, apc_php_free);
4392 +#ifdef ZEND_ENGINE_2
4393 + my_fixup_hashtable(&dst->function_table, (ht_fixup_fun_t)my_fixup_function_for_execution, src, dst);
4395 + /* zend_do_inheritance merges properties_info.
4396 + * Need only shallow copying as it doesn't hold the pointers.
4398 + my_copy_hashtable(&dst->properties_info,
4399 + &src->properties_info,
4400 + (ht_copy_fun_t) my_copy_property_info_for_execution,
4403 + apc_php_malloc, apc_php_free);
4405 +#ifdef ZEND_ENGINE_2_2
4406 + /* php5.2 introduced a scope attribute for property info */
4407 + my_fixup_hashtable(&dst->properties_info, (ht_fixup_fun_t)my_fixup_property_info_for_execution, src, dst);
4410 + /* if inheritance results in a hash_del, it might result in
4411 + * a pefree() of the pointers here. Deep copying required.
4414 + my_copy_hashtable(&dst->constants_table,
4415 + &src->constants_table,
4416 + (ht_copy_fun_t) my_copy_zval_ptr,
4419 + apc_php_malloc, apc_php_free);
4421 + my_copy_hashtable(&dst->default_static_members,
4422 + &src->default_static_members,
4423 + (ht_copy_fun_t) my_copy_zval_ptr,
4424 + (ht_free_fun_t) my_free_zval_ptr,
4426 + apc_php_malloc, apc_php_free);
4428 + if(src->static_members != &(src->default_static_members))
4430 + dst->static_members = my_copy_hashtable(NULL,
4431 + src->static_members,
4432 + (ht_copy_fun_t) my_copy_zval_ptr,
4433 + (ht_free_fun_t) my_free_zval_ptr,
4435 + apc_php_malloc, apc_php_free);
4439 + dst->static_members = &(dst->default_static_members);
4448 +/* {{{ apc_free_class_entry_after_execution */
4449 +void apc_free_class_entry_after_execution(zend_class_entry* src)
4451 +#ifdef ZEND_ENGINE_2
4452 + if(src->num_interfaces > 0 && src->interfaces) {
4453 + apc_php_free(src->interfaces);
4454 + src->interfaces = NULL;
4455 + src->num_interfaces = 0;
4457 + /* my_destroy_hashtable() does not play nice with refcounts */
4459 + zend_hash_clean(&src->default_static_members);
4460 + if(src->static_members != &(src->default_static_members))
4462 + zend_hash_destroy(src->static_members);
4463 + apc_php_free(src->static_members);
4464 + src->static_members = NULL;
4468 + src->static_members = NULL;
4470 + zend_hash_clean(&src->default_properties);
4471 + zend_hash_clean(&src->constants_table);
4474 + /* TODO: more cleanup */
4478 +#ifdef ZEND_ENGINE_2
4480 +/* {{{ my_fixup_function */
4481 +static void my_fixup_function(Bucket *p, zend_class_entry *src, zend_class_entry *dst)
4483 + zend_function* zf = p->pData;
4485 + #define SET_IF_SAME_NAME(member) \
4487 + if(src->member && !strcmp(zf->common.function_name, src->member->common.function_name)) { \
4488 + dst->member = zf; \
4493 + if(zf->common.scope == src)
4496 + /* Fixing up the default functions for objects here since
4497 + * we need to compare with the newly allocated functions
4499 + * caveat: a sub-class method can have the same name as the
4500 + * parent's constructor and create problems.
4503 + if(zf->common.fn_flags & ZEND_ACC_CTOR) dst->constructor = zf;
4504 + else if(zf->common.fn_flags & ZEND_ACC_DTOR) dst->destructor = zf;
4505 + else if(zf->common.fn_flags & ZEND_ACC_CLONE) dst->clone = zf;
4508 + SET_IF_SAME_NAME(__get);
4509 + SET_IF_SAME_NAME(__set);
4510 + SET_IF_SAME_NAME(__unset);
4511 + SET_IF_SAME_NAME(__isset);
4512 + SET_IF_SAME_NAME(__call);
4513 +#ifdef ZEND_ENGINE_2_2
4514 + SET_IF_SAME_NAME(__tostring);
4517 + zf->common.scope = dst;
4521 + /* no other function should reach here */
4525 + #undef SET_IF_SAME_NAME
4529 +#ifdef ZEND_ENGINE_2_2
4530 +/* {{{ my_fixup_property_info */
4531 +static void my_fixup_property_info(Bucket *p, zend_class_entry *src, zend_class_entry *dst)
4533 + zend_property_info* property_info = (zend_property_info*)p->pData;
4535 + if(property_info->ce == src)
4537 + property_info->ce = dst;
4541 + assert(0); /* should never happen */
4547 +/* {{{ my_fixup_hashtable */
4548 +static void my_fixup_hashtable(HashTable *ht, ht_fixup_fun_t fixup, zend_class_entry *src, zend_class_entry *dst)
4554 + for (i = 0; i < ht->nTableSize; i++) {
4555 + if(!ht->arBuckets) break;
4556 + p = ht->arBuckets[i];
4557 + while (p != NULL) {
4558 + fixup(p, src, dst);
4567 +/* {{{ my_check_copy_function */
4568 +static int my_check_copy_function(Bucket* p, va_list args)
4570 + zend_class_entry* src = va_arg(args, zend_class_entry*);
4571 + zend_function* zf = (zend_function*)p->pData;
4572 +#ifndef ZEND_ENGINE_2
4573 + zend_class_entry* parent = src->parent;
4574 + zend_function* parent_fn = NULL;
4577 +#ifdef ZEND_ENGINE_2
4578 + return (zf->common.scope == src);
4581 + zend_hash_quick_find(&parent->function_table, p->arKey,
4582 + p->nKeyLength, p->h, (void **) &parent_fn)==SUCCESS) {
4584 + if((parent_fn && zf) &&
4585 + (parent_fn->op_array.refcount == zf->op_array.refcount))
4595 +/* {{{ my_check_copy_default_property */
4596 +static int my_check_copy_default_property(Bucket* p, va_list args)
4598 + zend_class_entry* src = va_arg(args, zend_class_entry*);
4599 + zend_class_entry* parent = src->parent;
4600 + zval ** child_prop = (zval**)p->pData;
4601 + zval ** parent_prop = NULL;
4604 + zend_hash_quick_find(&parent->default_properties, p->arKey,
4605 + p->nKeyLength, p->h, (void **) &parent_prop)==SUCCESS) {
4607 + if((parent_prop && child_prop) && (*parent_prop) == (*child_prop))
4613 + /* possibly not in the parent */
4618 +#ifdef ZEND_ENGINE_2
4620 +/* {{{ my_check_copy_property_info */
4621 +static int my_check_copy_property_info(Bucket* p, va_list args)
4623 + zend_class_entry* src = va_arg(args, zend_class_entry*);
4624 + zend_class_entry* parent = src->parent;
4625 + zend_property_info* child_info = (zend_property_info*)p->pData;
4626 + zend_property_info* parent_info = NULL;
4628 +#ifdef ZEND_ENGINE_2_2
4629 + /* so much easier */
4630 + return (child_info->ce == src);
4634 + zend_hash_quick_find(&parent->properties_info, p->arKey, p->nKeyLength,
4635 + p->h, (void **) &parent_info)==SUCCESS) {
4636 + if(parent_info->flags & ZEND_ACC_PRIVATE)
4640 + if((parent_info->flags & ZEND_ACC_PPP_MASK) !=
4641 + (child_info->flags & ZEND_ACC_PPP_MASK))
4643 + /* TODO: figure out whether ACC_CHANGED is more appropriate
4650 + /* property doesn't exist in parent, copy into cached child */
4655 +/* {{{ my_check_copy_static_member */
4656 +static int my_check_copy_static_member(Bucket* p, va_list args)
4658 + zend_class_entry* src = va_arg(args, zend_class_entry*);
4659 + HashTable * ht = va_arg(args, HashTable*);
4660 + zend_class_entry* parent = src->parent;
4661 + HashTable * parent_ht = NULL;
4662 + char * member_name;
4663 + char * class_name = NULL;
4665 + zend_property_info *parent_info = NULL;
4666 + zend_property_info *child_info = NULL;
4667 + zval ** parent_prop = NULL;
4668 + zval ** child_prop = (zval**)(p->pData);
4674 + /* these do not need free'ing */
4675 +#ifdef ZEND_ENGINE_2_2
4676 + zend_unmangle_property_name(p->arKey, p->nKeyLength-1, &class_name, &member_name);
4678 + zend_unmangle_property_name(p->arKey, &class_name, &member_name);
4681 + /* please refer do_inherit_property_access_check in zend_compile.c
4682 + * to understand why we lookup in properties_info.
4684 + if((zend_hash_find(&parent->properties_info, member_name,
4685 + strlen(member_name)+1, (void**)&parent_info) == SUCCESS)
4687 + (zend_hash_find(&src->properties_info, member_name,
4688 + strlen(member_name)+1, (void**)&child_info) == SUCCESS))
4690 + if(child_info->flags & ZEND_ACC_STATIC &&
4691 + (parent_info->flags & ZEND_ACC_PROTECTED &&
4692 + child_info->flags & ZEND_ACC_PUBLIC))
4694 + /* Do not copy into static_members. zend_do_inheritance
4695 + * will automatically insert a NULL value.
4696 + * TODO: decrement refcount or fixup when copying out for exec ?
4700 + if(ht == &(src->default_static_members))
4702 + parent_ht = &parent->default_static_members;
4706 + parent_ht = parent->static_members;
4709 + if(zend_hash_quick_find(parent_ht, p->arKey,
4710 + p->nKeyLength, p->h, (void**)&parent_prop) == SUCCESS)
4712 + /* they point to the same zval */
4713 + if(*parent_prop == *child_prop)
4725 +/* {{{ apc_register_optimizer(apc_optimize_function_t optimizer)
4726 + * register a optimizer callback function, returns the previous callback
4728 +apc_optimize_function_t apc_register_optimizer(apc_optimize_function_t optimizer TSRMLS_DC) {
4729 + apc_optimize_function_t old_optimizer = APCG(apc_optimize_function);
4730 + APCG(apc_optimize_function) = optimizer;
4731 + return old_optimizer;
4735 + * Local variables:
4737 + * c-basic-offset: 4
4739 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
4740 + * vim<600: expandtab sw=4 ts=4 sts=4
4742 diff -ruN php-5.1.6.old/ext/apc/apc_compile.h php-5.1.6/ext/APC/apc_compile.h
4743 --- php-5.1.6.old/ext/apc/apc_compile.h 1969-12-31 18:00:00.000000000 -0600
4744 +++ php-5.1.6/ext/apc/apc_compile.h 2007-04-02 18:05:30.000000000 -0500
4747 + +----------------------------------------------------------------------+
4749 + +----------------------------------------------------------------------+
4750 + | Copyright (c) 2006 The PHP Group |
4751 + +----------------------------------------------------------------------+
4752 + | This source file is subject to version 3.01 of the PHP license, |
4753 + | that is bundled with this package in the file LICENSE, and is |
4754 + | available through the world-wide-web at the following url: |
4755 + | http://www.php.net/license/3_01.txt |
4756 + | If you did not receive a copy of the PHP license and are unable to |
4757 + | obtain it through the world-wide-web, please send a note to |
4758 + | license@php.net so we can mail you a copy immediately. |
4759 + +----------------------------------------------------------------------+
4760 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
4761 + | Arun C. Murthy <arunc@yahoo-inc.com> |
4762 + | Gopal Vijayaraghavan <gopalv@yahoo-inc.com> |
4763 + +----------------------------------------------------------------------+
4765 + This software was contributed to PHP by Community Connect Inc. in 2002
4766 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
4767 + Future revisions and derivatives of this source code must acknowledge
4768 + Community Connect Inc. as the original contributor of this module by
4769 + leaving this note intact in the source code.
4771 + All other licensing and usage conditions are those of the PHP Group.
4775 +/* $Id: apc_compile.h,v 3.19 2007/03/08 22:03:35 gopalv Exp $ */
4777 +#ifndef APC_COMPILE_H
4778 +#define APC_COMPILE_H
4781 + * This module encapsulates most of the complexity involved in deep-copying
4782 + * the Zend compiler data structures. The routines are allocator-agnostic, so
4783 + * the same function can be used for copying to and from shared memory.
4787 +#include "apc_php.h"
4789 +/* {{{ struct definition: apc_function_t */
4790 +typedef struct apc_function_t apc_function_t;
4791 +struct apc_function_t {
4792 + char* name; /* the function name */
4793 + int name_len; /* length of name */
4794 + zend_function* function; /* the zend function data structure */
4798 +/* {{{ struct definition: apc_class_t */
4799 +typedef struct apc_class_t apc_class_t;
4800 +struct apc_class_t {
4801 + char* name; /* the class name */
4802 + int name_len; /* length of name */
4803 + int is_derived; /* true if this is a derived class */
4804 + char* parent_name; /* the parent class name */
4805 + zend_class_entry* class_entry; /* the zend class data structure */
4809 +/* {{{ struct definition: apc_opflags_t */
4810 +typedef struct apc_opflags_t apc_opflags_t;
4811 +struct apc_opflags_t {
4812 + unsigned int has_jumps : 1; /* has jump offsets */
4813 + unsigned int deep_copy : 1; /* needs deep copy */
4815 + /* autoglobal bits */
4816 + unsigned int _POST : 1;
4817 + unsigned int _GET : 1;
4818 + unsigned int _COOKIE : 1;
4819 + unsigned int _SERVER : 1;
4820 + unsigned int _ENV : 1;
4821 + unsigned int _FILES : 1;
4822 + unsigned int _REQUEST : 1;
4823 + unsigned int unknown_global : 1;
4828 + * These are the top-level copy functions.
4831 +extern zend_op_array* apc_copy_op_array(zend_op_array* dst, zend_op_array* src, apc_malloc_t allocate, apc_free_t deallocate TSRMLS_DC);
4832 +extern zend_class_entry* apc_copy_class_entry(zend_class_entry* dst, zend_class_entry* src, apc_malloc_t allocate, apc_free_t deallocate);
4833 +extern apc_function_t* apc_copy_new_functions(int old_count, apc_malloc_t allocate, apc_free_t deallocate TSRMLS_DC);
4834 +extern apc_class_t* apc_copy_new_classes(zend_op_array* op_array, int old_count, apc_malloc_t allocate, apc_free_t deallocate TSRMLS_DC);
4835 +extern zval* apc_copy_zval(zval* dst, const zval* src, apc_malloc_t allocate, apc_free_t deallocate);
4838 + * Deallocation functions corresponding to the copy functions above.
4841 +extern void apc_free_op_array(zend_op_array* src, apc_free_t deallocate);
4842 +extern void apc_free_functions(apc_function_t* src, apc_free_t deallocate);
4843 +extern void apc_free_classes(apc_class_t* src, apc_free_t deallocate);
4844 +extern void apc_free_zval(zval* src, apc_free_t deallocate);
4847 + * These "copy-for-execution" functions must be called after retrieving an
4848 + * object from the shared cache. They do the minimal amount of work necessary
4849 + * to allow multiple processes to concurrently execute the same VM data
4853 +extern zend_op_array* apc_copy_op_array_for_execution(zend_op_array* dst, zend_op_array* src TSRMLS_DC);
4854 +extern zend_function* apc_copy_function_for_execution(zend_function* src);
4855 +extern zend_class_entry* apc_copy_class_entry_for_execution(zend_class_entry* src, int is_derived);
4858 + * The "free-after-execution" function performs a cursory clean up of the class data
4859 + * This is required to minimize memory leak warnings and to ensure correct destructor
4860 + * ordering of some variables.
4862 +extern void apc_free_class_entry_after_execution(zend_class_entry* src);
4865 + * Optimization callback definition and registration function.
4867 +typedef zend_op_array* (*apc_optimize_function_t) (zend_op_array* TSRMLS_DC);
4868 +extern apc_optimize_function_t apc_register_optimizer(apc_optimize_function_t optimizer TSRMLS_DC);
4873 + * Local variables:
4875 + * c-basic-offset: 4
4877 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
4878 + * vim<600: expandtab sw=4 ts=4 sts=4
4880 diff -ruN php-5.1.6.old/ext/apc/apc_debug.c php-5.1.6/ext/APC/apc_debug.c
4881 --- php-5.1.6.old/ext/apc/apc_debug.c 1969-12-31 18:00:00.000000000 -0600
4882 +++ php-5.1.6/ext/apc/apc_debug.c 2007-04-02 18:05:30.000000000 -0500
4885 + +----------------------------------------------------------------------+
4887 + +----------------------------------------------------------------------+
4888 + | Copyright (c) 2006 The PHP Group |
4889 + +----------------------------------------------------------------------+
4890 + | This source file is subject to version 3.01 of the PHP license, |
4891 + | that is bundled with this package in the file LICENSE, and is |
4892 + | available through the world-wide-web at the following url: |
4893 + | http://www.php.net/license/3_01.txt |
4894 + | If you did not receive a copy of the PHP license and are unable to |
4895 + | obtain it through the world-wide-web, please send a note to |
4896 + | license@php.net so we can mail you a copy immediately. |
4897 + +----------------------------------------------------------------------+
4898 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
4899 + | Arun C. Murthy <arunc@yahoo-inc.com> |
4900 + | Gopal Vijayaraghavan <gopalv@yahoo-inc.com> |
4901 + +----------------------------------------------------------------------+
4903 + This software was contributed to PHP by Community Connect Inc. in 2002
4904 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
4905 + Future revisions and derivatives of this source code must acknowledge
4906 + Community Connect Inc. as the original contributor of this module by
4907 + leaving this note intact in the source code.
4909 + All other licensing and usage conditions are those of the PHP Group.
4912 +/* $Id: apc_debug.c,v 3.6 2006/12/07 23:51:28 gopalv Exp $ */
4915 +#include "zend_compile.h"
4917 +#ifdef __DEBUG_APC__
4921 +/* keep track of vld_dump_oparray() signature */
4922 +typedef void (*vld_dump_f) (zend_op_array * TSRMLS_DC);
4926 +void dump(zend_op_array *op_array TSRMLS_DC)
4928 +#ifdef __DEBUG_APC__
4929 + vld_dump_f dump_op_array = dlsym(NULL, "vld_dump_oparray");
4933 + dump_op_array(op_array TSRMLS_CC);
4937 + apc_wprint("vld is not installed or something even worse.");
4941 diff -ruN php-5.1.6.old/ext/apc/apc_debug.h php-5.1.6/ext/APC/apc_debug.h
4942 --- php-5.1.6.old/ext/apc/apc_debug.h 1969-12-31 18:00:00.000000000 -0600
4943 +++ php-5.1.6/ext/apc/apc_debug.h 2007-04-02 18:05:30.000000000 -0500
4945 +void dump(zend_op_array * TSRMLS_DC);
4946 diff -ruN php-5.1.6.old/ext/apc/apc.dsp php-5.1.6/ext/APC/apc.dsp
4947 --- php-5.1.6.old/ext/apc/apc.dsp 1969-12-31 18:00:00.000000000 -0600
4948 +++ php-5.1.6/ext/apc/apc.dsp 2007-04-02 18:05:30.000000000 -0500
4950 +# Microsoft Developer Studio Project File - Name="apc" - Package Owner=<4>
4951 +# Microsoft Developer Studio Generated Build File, Format Version 6.00
4952 +# ** DO NOT EDIT **
4954 +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
4956 +CFG=apc - Win32 Debug_TS
4957 +!MESSAGE This is not a valid makefile. To build this project using NMAKE,
4958 +!MESSAGE use the Export Makefile command and run
4960 +!MESSAGE NMAKE /f "apc.mak".
4962 +!MESSAGE You can specify a configuration when running NMAKE
4963 +!MESSAGE by defining the macro CFG on the command line. For example:
4965 +!MESSAGE NMAKE /f "apc.mak" CFG="apc - Win32 Debug_TS"
4967 +!MESSAGE Possible choices for configuration are:
4969 +!MESSAGE "apc - Win32 Debug_TS" (based on "Win32 (x86) Dynamic-Link Library")
4970 +!MESSAGE "apc - Win32 Release_TS" (based on "Win32 (x86) Dynamic-Link Library")
4974 +# PROP AllowPerConfigDependencies 0
4975 +# PROP Scc_ProjName ""
4976 +# PROP Scc_LocalPath ""
4981 +!IF "$(CFG)" == "apc - Win32 Debug_TS"
4983 +# PROP BASE Use_MFC 0
4984 +# PROP BASE Use_Debug_Libraries 1
4985 +# PROP BASE Output_Dir "Debug_TS"
4986 +# PROP BASE Intermediate_Dir "Debug_TS"
4987 +# PROP BASE Target_Dir ""
4989 +# PROP Use_Debug_Libraries 1
4990 +# PROP Output_Dir "Debug_TS"
4991 +# PROP Intermediate_Dir "Debug_TS"
4992 +# PROP Ignore_Export_Lib 0
4993 +# PROP Target_Dir ""
4994 +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "APC_EXPORTS" /YX /FD /GZ /c
4995 +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\php4" /I "..\..\..\php4\main" /I "..\..\..\php4\Zend" /I "..\..\..\php4\TSRM" /I "..\..\..\php4\win32" /I "..\..\..\php4\regex" /D "TSRM_LOCKS" /D HAVE_APC=1 /D "COMPILE_DL_APC" /D ZEND_DEBUG=1 /D ZTS=1 /D "ZEND_WIN32" /D "PHP_WIN32" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "APC_EXPORTS" /YX /FD /GZ /c
4996 +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
4997 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
4998 +# ADD BASE RSC /l 0x409 /d "_DEBUG"
4999 +# ADD RSC /l 0x409 /d "_DEBUG"
5001 +# ADD BASE BSC32 /nologo
5002 +# ADD BSC32 /nologo
5004 +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
5005 +# ADD LINK32 php4ts_debug.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"Debug_TS/php_apc.dll" /pdbtype:sept /libpath:"..\..\..\php4\Debug_TS"
5007 +!ELSEIF "$(CFG)" == "apc - Win32 Release_TS"
5009 +# PROP BASE Use_MFC 0
5010 +# PROP BASE Use_Debug_Libraries 0
5011 +# PROP BASE Output_Dir "Release_TS"
5012 +# PROP BASE Intermediate_Dir "Release_TS"
5013 +# PROP BASE Target_Dir ""
5015 +# PROP Use_Debug_Libraries 0
5016 +# PROP Output_Dir "Release_TS"
5017 +# PROP Intermediate_Dir "Release_TS"
5018 +# PROP Ignore_Export_Lib 0
5019 +# PROP Target_Dir ""
5020 +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "APC_EXPORTS" /YX /FD /c
5021 +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\..\php4" /I "..\..\..\php4\main" /I "..\..\..\php4\Zend" /I "..\..\..\php4\TSRM" /I "..\..\..\php4\win32" /I "..\..\..\php4\regex" /D "TSRM_LOCKS" /D HAVE_APC=1 /D "COMPILE_DL_APC" /D ZEND_DEBUG=0 /D ZTS=1 /D "ZEND_WIN32" /D "PHP_WIN32" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "APC_EXPORTS" /YX /FD /c
5022 +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
5023 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
5024 +# ADD BASE RSC /l 0x409 /d "NDEBUG"
5025 +# ADD RSC /l 0x409 /d "NDEBUG"
5027 +# ADD BASE BSC32 /nologo
5028 +# ADD BSC32 /nologo
5030 +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
5031 +# ADD LINK32 php4ts.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"../../Release_TS/php_apc.dll" /libpath:"..\..\..\php4\Release_TS" /libpath:"..\..\..\php4\Release_TS_Inline"
5037 +# Name "apc - Win32 Debug_TS"
5038 +# Name "apc - Win32 Release_TS"
5039 +# Begin Group "Source Files"
5041 +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
5042 +# Begin Source File
5046 +# Begin Source File
5048 +SOURCE=.\apc_cache.c
5050 +# Begin Source File
5052 +SOURCE=.\apc_compile.c
5054 +# Begin Source File
5056 +SOURCE=.\apc_debug.c
5058 +# Begin Source File
5060 +SOURCE=.\apc_fcntl_win32.c
5062 +# Begin Source File
5064 +SOURCE=.\apc_main.c
5066 +# Begin Source File
5068 +SOURCE=.\apc_rfc1867.c
5070 +# Begin Source File
5074 +# Begin Source File
5078 +# Begin Source File
5080 +SOURCE=.\apc_stack.c
5082 +# Begin Source File
5084 +SOURCE=.\apc_zend.c
5086 +# Begin Source File
5091 +# Begin Group "Header Files"
5093 +# PROP Default_Filter "h;hpp;hxx;hm;inl"
5094 +# Begin Source File
5098 +# Begin Source File
5100 +SOURCE=.\apc_cache.h
5102 +# Begin Source File
5104 +SOURCE=.\apc_compile.h
5106 +# Begin Source File
5108 +SOURCE=.\apc_debug.h
5110 +# Begin Source File
5112 +SOURCE=.\apc_fcntl.h
5114 +# Begin Source File
5116 +SOURCE=.\apc_globals.h
5118 +# Begin Source File
5120 +SOURCE=.\apc_lock.h
5122 +# Begin Source File
5124 +SOURCE=.\apc_main.h
5126 +# Begin Source File
5130 +# Begin Source File
5134 +# Begin Source File
5138 +# Begin Source File
5140 +SOURCE=.\apc_stack.h
5142 +# Begin Source File
5144 +SOURCE=.\apc_zend.h
5146 +# Begin Source File
5151 +# Begin Group "Resource Files"
5153 +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
5157 diff -ruN php-5.1.6.old/ext/apc/apc_fcntl.c php-5.1.6/ext/APC/apc_fcntl.c
5158 --- php-5.1.6.old/ext/apc/apc_fcntl.c 1969-12-31 18:00:00.000000000 -0600
5159 +++ php-5.1.6/ext/apc/apc_fcntl.c 2007-04-02 18:05:30.000000000 -0500
5162 + +----------------------------------------------------------------------+
5164 + +----------------------------------------------------------------------+
5165 + | Copyright (c) 2006 The PHP Group |
5166 + +----------------------------------------------------------------------+
5167 + | This source file is subject to version 3.01 of the PHP license, |
5168 + | that is bundled with this package in the file LICENSE, and is |
5169 + | available through the world-wide-web at the following url: |
5170 + | http://www.php.net/license/3_01.txt |
5171 + | If you did not receive a copy of the PHP license and are unable to |
5172 + | obtain it through the world-wide-web, please send a note to |
5173 + | license@php.net so we can mail you a copy immediately. |
5174 + +----------------------------------------------------------------------+
5175 + | Authors: George Schlossnagle <george@omniti.com> |
5176 + | Rasmus Lerdorf <rasmus@php.net> |
5177 + +----------------------------------------------------------------------+
5179 + This software was contributed to PHP by Community Connect Inc. in 2002
5180 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
5181 + Future revisions and derivatives of this source code must acknowledge
5182 + Community Connect Inc. as the original contributor of this module by
5183 + leaving this note intact in the source code.
5185 + All other licensing and usage conditions are those of the PHP Group.
5189 +/* $Id: apc_fcntl.c,v 3.25 2006/06/19 02:52:49 rasmus Exp $ */
5191 +#include "apc_fcntl.h"
5193 +#include <unistd.h>
5196 +int apc_fcntl_create(const char* pathname)
5199 + if(pathname == NULL) {
5200 + char lock_path[] = "/tmp/.apc.XXXXXX";
5201 + mktemp(lock_path);
5202 + fd = open(lock_path, O_RDWR|O_CREAT, 0666);
5204 + unlink(lock_path);
5207 + apc_eprint("apc_fcntl_create: open(%s, O_RDWR|O_CREAT, 0666) failed:", lock_path);
5211 + fd = open(pathname, O_RDWR|O_CREAT, 0666);
5216 + apc_eprint("apc_fcntl_create: open(%s, O_RDWR|O_CREAT, 0666) failed:", pathname);
5220 +void apc_fcntl_destroy(int fd)
5225 +static int lock_reg(int fd, int cmd, int type, off_t offset, int whence, off_t len)
5228 + struct flock lock;
5230 + lock.l_type = type;
5231 + lock.l_start = offset;
5232 + lock.l_whence = whence;
5236 + do { ret = fcntl(fd, cmd, &lock) ; }
5237 + while(ret < 0 && errno == EINTR);
5241 +void apc_fcntl_lock(int fd)
5243 + if(lock_reg(fd, F_SETLKW, F_WRLCK, 0, SEEK_SET, 0) < 0) {
5244 + apc_eprint("apc_fcntl_lock failed:");
5248 +void apc_fcntl_rdlock(int fd)
5250 + if(lock_reg(fd, F_SETLKW, F_RDLCK, 0, SEEK_SET, 0) < 0) {
5251 + apc_eprint("apc_fcntl_rdlock failed:");
5255 +zend_bool apc_fcntl_nonblocking_lock(int fd)
5257 + if(lock_reg(fd, F_SETLK, F_WRLCK, 0, SEEK_SET, 0) < 0) {
5258 + if(errno==EACCES||errno==EAGAIN) return 0;
5259 + else apc_eprint("apc_fcntl_lock failed:");
5264 +void apc_fcntl_unlock(int fd)
5266 + if(lock_reg(fd, F_SETLKW, F_UNLCK, 0, SEEK_SET, 0) < 0) {
5267 + apc_eprint("apc_fcntl_unlock failed:");
5272 + * Local variables:
5274 + * c-basic-offset: 4
5276 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
5277 + * vim<600: expandtab sw=4 ts=4 sts=4
5279 diff -ruN php-5.1.6.old/ext/apc/apc_fcntl.h php-5.1.6/ext/APC/apc_fcntl.h
5280 --- php-5.1.6.old/ext/apc/apc_fcntl.h 1969-12-31 18:00:00.000000000 -0600
5281 +++ php-5.1.6/ext/apc/apc_fcntl.h 2007-04-02 18:05:30.000000000 -0500
5284 + +----------------------------------------------------------------------+
5286 + +----------------------------------------------------------------------+
5287 + | Copyright (c) 2006 The PHP Group |
5288 + +----------------------------------------------------------------------+
5289 + | This source file is subject to version 3.01 of the PHP license, |
5290 + | that is bundled with this package in the file LICENSE, and is |
5291 + | available through the world-wide-web at the following url: |
5292 + | http://www.php.net/license/3_01.txt. |
5293 + | If you did not receive a copy of the PHP license and are unable to |
5294 + | obtain it through the world-wide-web, please send a note to |
5295 + | license@php.net so we can mail you a copy immediately. |
5296 + +----------------------------------------------------------------------+
5297 + | Authors: George Schlossnagle <george@omniti.com> |
5298 + | Rasmus Lerdorf <rasmus@php.net> |
5299 + +----------------------------------------------------------------------+
5301 + This software was contributed to PHP by Community Connect Inc. in 2002
5302 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
5303 + Future revisions and derivatives of this source code must acknowledge
5304 + Community Connect Inc. as the original contributor of this module by
5305 + leaving this note intact in the source code.
5307 + All other licensing and usage conditions are those of the PHP Group.
5311 +/* $Id: apc_fcntl.h,v 3.14 2006/05/31 22:24:48 rasmus Exp $ */
5313 +#ifndef APC_FCNTL_H
5314 +#define APC_FCNTL_H
5317 +extern int apc_fcntl_create(const char* pathname);
5318 +extern void apc_fcntl_destroy(int fd);
5319 +extern void apc_fcntl_lock(int fd);
5320 +extern void apc_fcntl_rdlock(int fd);
5321 +extern void apc_fcntl_unlock(int fd);
5322 +extern unsigned char apc_fcntl_nonblocking_lock(int fd);
5326 + * Local variables:
5328 + * c-basic-offset: 4
5330 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
5331 + * vim<600: expandtab sw=4 ts=4 sts=4
5333 diff -ruN php-5.1.6.old/ext/apc/apc_fcntl_win32.c php-5.1.6/ext/APC/apc_fcntl_win32.c
5334 --- php-5.1.6.old/ext/apc/apc_fcntl_win32.c 1969-12-31 18:00:00.000000000 -0600
5335 +++ php-5.1.6/ext/apc/apc_fcntl_win32.c 2007-04-02 18:05:30.000000000 -0500
5338 + +----------------------------------------------------------------------+
5340 + +----------------------------------------------------------------------+
5341 + | Copyright (c) 2006 The PHP Group |
5342 + +----------------------------------------------------------------------+
5343 + | This source file is subject to version 3.01 of the PHP license, |
5344 + | that is bundled with this package in the file LICENSE, and is |
5345 + | available through the world-wide-web at the following url: |
5346 + | http://www.php.net/license/3_01.txt |
5347 + | If you did not receive a copy of the PHP license and are unable to |
5348 + | obtain it through the world-wide-web, please send a note to |
5349 + | license@php.net so we can mail you a copy immediately. |
5350 + +----------------------------------------------------------------------+
5351 + | Authors: George Schlossnagle <george@omniti.com> |
5352 + | Edin Kadribasic <edink@php.net> |
5353 + +----------------------------------------------------------------------+
5355 + This software was contributed to PHP by Community Connect Inc. in 2002
5356 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
5357 + Future revisions and derivatives of this source code must acknowledge
5358 + Community Connect Inc. as the original contributor of this module by
5359 + leaving this note intact in the source code.
5361 + All other licensing and usage conditions are those of the PHP Group.
5365 +/* $Id: apc_fcntl_win32.c,v 3.6 2006/03/12 00:31:45 rasmus Exp $ */
5367 +#include "apc_fcntl.h"
5370 +#include <win32/flock.h>
5373 +#include <sys/types.h>
5374 +#include <sys/stat.h>
5376 +int apc_fcntl_create(const char* pathname)
5378 + char *lock_file = emalloc(MAXPATHLEN);
5383 + tmplen = GetTempPath(MAXPATHLEN, lock_file);
5389 + snprintf(lock_file + tmplen, MAXPATHLEN - tmplen - 1, "apc.lock.%d", i++);
5391 + fd = CreateFile(lock_file,
5392 + GENERIC_READ | GENERIC_WRITE,
5393 + FILE_SHARE_READ | FILE_SHARE_WRITE,
5396 + FILE_ATTRIBUTE_NORMAL,
5400 + if (fd == INVALID_HANDLE_VALUE) {
5401 + apc_eprint("apc_fcntl_create: could not open %s", lock_file);
5410 +void apc_fcntl_destroy(int fd)
5412 + CloseHandle((HANDLE)fd);
5415 +void apc_fcntl_lock(int fd)
5417 + OVERLAPPED offset = {0, 0, 0, 0, NULL};
5419 + if (!LockFileEx((HANDLE)fd, LOCKFILE_EXCLUSIVE_LOCK, 0, 1, 0, &offset)) {
5420 + apc_eprint("apc_fcntl_lock failed errno:%d", GetLastError());
5424 +void apc_fcntl_rdlock(int fd)
5426 + OVERLAPPED offset = {0, 0, 0, 0, NULL};
5428 + if (!LockFileEx((HANDLE)fd, 0, 0, 1, 0, &offset)) {
5429 + apc_eprint("apc_fcntl_rdlock failed errno:%d", GetLastError());
5433 +void apc_fcntl_unlock(int fd)
5435 + OVERLAPPED offset = {0, 0, 0, 0, NULL};
5437 + if (!UnlockFileEx((HANDLE)fd, 0, 1, 0, &offset)) {
5438 + DWORD error_code = GetLastError();
5439 + /* Ignore already unlocked error */
5440 + if (error_code != ERROR_NOT_LOCKED) {
5441 + apc_eprint("apc_fcntl_unlock failed errno:%d", error_code);
5447 + * Local variables:
5449 + * c-basic-offset: 4
5451 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
5452 + * vim<600: expandtab sw=4 ts=4 sts=4
5454 diff -ruN php-5.1.6.old/ext/apc/apc_futex.c php-5.1.6/ext/APC/apc_futex.c
5455 --- php-5.1.6.old/ext/apc/apc_futex.c 1969-12-31 18:00:00.000000000 -0600
5456 +++ php-5.1.6/ext/apc/apc_futex.c 2007-04-02 18:05:30.000000000 -0500
5459 + +----------------------------------------------------------------------+
5461 + +----------------------------------------------------------------------+
5462 + | Copyright (c) 2006 The PHP Group |
5463 + +----------------------------------------------------------------------+
5464 + | This source file is subject to version 3.01 of the PHP license, |
5465 + | that is bundled with this package in the file LICENSE, and is |
5466 + | available through the world-wide-web at the following url: |
5467 + | http://www.php.net/license/3_01.txt |
5468 + | If you did not receive a copy of the PHP license and are unable to |
5469 + | obtain it through the world-wide-web, please send a note to |
5470 + | license@php.net so we can mail you a copy immediately. |
5471 + +----------------------------------------------------------------------+
5472 + | Authors: Brian Shire <shire@php.net> |
5473 + +----------------------------------------------------------------------+
5477 +/* $Id: apc_futex.c,v 3.2 2006/10/12 08:23:16 shire Exp $ */
5479 +/***************************************************************************
5480 +* Futex (Fast Userspace Mutex) support for APC
5482 +* Futex support provides user space locking with system calls only
5483 +* for the contended cases. Some required reading for this functionality is:
5485 +* 'Fuss, Futexes and Furwocks: Fast Userlevel Locking in Linux'
5486 +* by Hubertus Franke, Rusty Russell, and Matthew Kirkwood
5487 +* http://www.realitydiluted.com/nptl-uclibc/docs/futex.pdf
5489 +* 'Futexes are Tricky' by Ulrich Drepper
5490 +* http://people.redhat.com/drepper/futex.pdf
5493 +* This implementation is optimized and designed for the i386 and x86_64
5494 +* architectures. Other architectures may require additional design
5495 +* to efficiently and safely implement this functionality.
5499 +* 1 = Locked without any waiting processes
5500 +* 2 = Locked with an unknown number of waiting processes
5502 +***************************************************************************/
5505 +#include "apc_futex.h"
5507 +#ifdef APC_FUTEX_LOCKS
5510 +inline int apc_futex_create()
5515 +inline void apc_futex_destroy(volatile int* lock)
5520 +void apc_futex_lock(volatile int* lock)
5524 + /* Attempt to obtain a lock if not currently locked. If the previous
5525 + * value was not 0 then we did not obtain the lock, and must wait.
5526 + * If the previous value was 1 (has no waiting processes) then we
5527 + * set the lock to 2 before blocking on the futex wait operation.
5528 + * This implementation suffers from the possible difficulty of
5529 + * efficently implementing the atomic xchg operation on some
5530 + * architectures, and could also cause unecessary wake operations by
5531 + * setting the lock to 2 when there are no additional waiters.
5533 + if((c = apc_cmpxchg(lock, 0, 1)) != 0) {
5535 + c = apc_xchg(lock, 2);
5538 + apc_futex_wait(lock, 2);
5539 + c = apc_xchg(lock, 2);
5545 +/* non-blocking lock returns 1 when the lock has been obtained, 0 if it would block */
5546 +inline zend_bool apc_futex_nonblocking_lock(volatile int* lock)
5548 + return apc_cmpxchg(lock, 0, 1) == 0;
5552 +inline void apc_futex_unlock(volatile int* lock)
5554 + /* set the lock to 0, if it's previous values was not 1 (no waiters)
5555 + * then perform a wake operation on one process letting it know the lock
5556 + * is available. This is an optimization to save wake calls if there
5557 + * are no waiting processes for the lock
5559 + if(apc_xchg(lock,0) != 1) {
5560 + apc_futex_wake(lock, 1);
5567 + * Local variables:
5569 + * c-basic-offset: 4
5571 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
5572 + * vim<600: expandtab sw=4 ts=4 sts=4
5574 diff -ruN php-5.1.6.old/ext/apc/apc_futex.h php-5.1.6/ext/APC/apc_futex.h
5575 --- php-5.1.6.old/ext/apc/apc_futex.h 1969-12-31 18:00:00.000000000 -0600
5576 +++ php-5.1.6/ext/apc/apc_futex.h 2007-04-02 18:05:30.000000000 -0500
5579 + +----------------------------------------------------------------------+
5581 + +----------------------------------------------------------------------+
5582 + | Copyright (c) 2006 The PHP Group |
5583 + +----------------------------------------------------------------------+
5584 + | This source file is subject to version 3.01 of the PHP license, |
5585 + | that is bundled with this package in the file LICENSE, and is |
5586 + | available through the world-wide-web at the following url: |
5587 + | http://www.php.net/license/3_01.txt |
5588 + | If you did not receive a copy of the PHP license and are unable to |
5589 + | obtain it through the world-wide-web, please send a note to |
5590 + | license@php.net so we can mail you a copy immediately. |
5591 + +----------------------------------------------------------------------+
5592 + | Authors: Brian Shire <shire@php.net> |
5593 + +----------------------------------------------------------------------+
5597 +/* $Id: apc_futex.h,v 3.2 2006/10/12 08:23:16 shire Exp $ */
5599 +#ifndef APC_FUTEX_H
5600 +#define APC_FUTEX_H
5604 +#ifdef APC_FUTEX_LOCKS
5606 +#include <asm/types.h>
5607 +#include <unistd.h>
5608 +#include <linux/futex.h>
5610 +#include "arch/atomic.h"
5612 +#define sys_futex(futex, op, val, timeout) syscall(SYS_futex, futex, op, val, timeout)
5613 +#define apc_futex_wait(val, oldval) sys_futex((void*)val, FUTEX_WAIT, oldval, NULL)
5614 +#define apc_futex_wake(val, count) sys_futex((void*)val, FUTEX_WAKE, count, NULL)
5616 +int apc_futex_create();
5617 +void apc_futex_destroy(volatile int* lock);
5618 +void apc_futex_lock(volatile int* lock);
5619 +void apc_futex_unlock(volatile int* lock);
5626 + * Local variables:
5628 + * c-basic-offset: 4
5630 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
5631 + * vim<600: expandtab sw=4 ts=4 sts=4
5633 diff -ruN php-5.1.6.old/ext/apc/apc_globals.h php-5.1.6/ext/APC/apc_globals.h
5634 --- php-5.1.6.old/ext/apc/apc_globals.h 1969-12-31 18:00:00.000000000 -0600
5635 +++ php-5.1.6/ext/apc/apc_globals.h 2007-04-02 18:05:30.000000000 -0500
5638 + +----------------------------------------------------------------------+
5640 + +----------------------------------------------------------------------+
5641 + | Copyright (c) 2006 The PHP Group |
5642 + +----------------------------------------------------------------------+
5643 + | This source file is subject to version 3.01 of the PHP license, |
5644 + | that is bundled with this package in the file LICENSE, and is |
5645 + | available through the world-wide-web at the following url: |
5646 + | http://www.php.net/license/3_01.txt. |
5647 + | If you did not receive a copy of the PHP license and are unable to |
5648 + | obtain it through the world-wide-web, please send a note to |
5649 + | license@php.net so we can mail you a copy immediately. |
5650 + +----------------------------------------------------------------------+
5651 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
5652 + | George Schlossnagle <george@omniti.com> |
5653 + | Rasmus Lerdorf <rasmus@php.net> |
5654 + | Arun C. Murthy <arunc@yahoo-inc.com> |
5655 + | Gopal Vijayaraghavan <gopalv@yahoo-inc.com> |
5656 + +----------------------------------------------------------------------+
5658 + This software was contributed to PHP by Community Connect Inc. in 2002
5659 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
5660 + Future revisions and derivatives of this source code must acknowledge
5661 + Community Connect Inc. as the original contributor of this module by
5662 + leaving this note intact in the source code.
5664 + All other licensing and usage conditions are those of the PHP Group.
5668 +/* $Id: apc_globals.h,v 3.59 2007/03/21 21:07:28 rasmus Exp $ */
5670 +#ifndef APC_GLOBALS_H
5671 +#define APC_GLOBALS_H
5673 +#define APC_VERSION "3.0.14"
5675 +#include "apc_cache.h"
5676 +#include "apc_stack.h"
5677 +#include "apc_php.h"
5679 +ZEND_BEGIN_MODULE_GLOBALS(apc)
5680 + /* configuration parameters */
5681 + zend_bool enabled; /* if true, apc is enabled (defaults to true) */
5682 + long shm_segments; /* number of shared memory segments to use */
5683 + long shm_size; /* size of each shared memory segment (in MB) */
5684 + long num_files_hint; /* parameter to apc_cache_create */
5685 + long user_entries_hint;
5686 + long gc_ttl; /* parameter to apc_cache_create */
5687 + long ttl; /* parameter to apc_cache_create */
5690 + char *mmap_file_mask; /* mktemp-style file-mask to pass to mmap */
5692 + char** filters; /* array of regex filters that prevent caching */
5694 + /* module variables */
5695 + zend_bool initialized; /* true if module was initialized */
5696 + apc_stack_t* cache_stack; /* the stack of cached executable code */
5697 + zend_bool cache_by_default; /* true if files should be cached unless filtered out */
5698 + /* false if files should only be cached if filtered in */
5699 + long slam_defense; /* Probability of a process not caching an uncached file */
5700 + size_t* mem_size_ptr; /* size of blocks allocated to file being cached (NULL outside my_compile_file) */
5701 + long file_update_protection; /* Age in seconds before a file is eligible to be cached - 0 to disable */
5702 + zend_bool enable_cli; /* Flag to override turning APC off for CLI */
5703 + long max_file_size; /* Maximum size of file, in bytes that APC will be allowed to cache */
5704 + long slam_rand; /* A place to store the slam rand value for the request */
5705 + zend_bool fpstat; /* true if fullpath includes should be stat'ed */
5706 + zend_bool stat_ctime; /* true if ctime in addition to mtime should be checked */
5707 + zend_bool write_lock; /* true for a global write lock */
5708 + zend_bool report_autofilter; /* true for auto-filter warnings */
5709 + zend_bool include_once; /* Override the ZEND_INCLUDE_OR_EVAL opcode handler to avoid pointless fopen()s [still experimental] */
5710 + apc_optimize_function_t apc_optimize_function; /* optimizer function callback */
5711 +#ifdef MULTIPART_EVENT_FORMDATA
5712 + zend_bool rfc1867; /* Flag to enable rfc1867 handler */
5714 + HashTable *copied_zvals; /* my_copy recursion detection list */
5715 +#ifdef ZEND_ENGINE_2
5716 + int reserved_offset; /* offset for apc info in op_array->reserved[] */
5718 + zend_bool localcache; /* enable local cache */
5719 + long localcache_size; /* size of fast cache */
5720 + apc_local_cache_t* lcache; /* unlocked local cache */
5721 +ZEND_END_MODULE_GLOBALS(apc)
5723 +/* (the following declaration is defined in php_apc.c) */
5724 +ZEND_EXTERN_MODULE_GLOBALS(apc)
5727 +# define APCG(v) TSRMG(apc_globals_id, zend_apc_globals *, v)
5729 +# define APCG(v) (apc_globals.v)
5733 +extern apc_cache_t* apc_cache; /* the global compiler cache */
5734 +extern apc_cache_t* apc_user_cache; /* the global user content cache */
5735 +extern void* apc_compiled_filters; /* compiled filters */
5740 + * Local variables:
5742 + * c-basic-offset: 4
5744 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
5745 + * vim<600: expandtab sw=4 ts=4 sts=4
5747 diff -ruN php-5.1.6.old/ext/apc/apc.h php-5.1.6/ext/APC/apc.h
5748 --- php-5.1.6.old/ext/apc/apc.h 1969-12-31 18:00:00.000000000 -0600
5749 +++ php-5.1.6/ext/apc/apc.h 2007-04-02 18:05:30.000000000 -0500
5752 + +----------------------------------------------------------------------+
5754 + +----------------------------------------------------------------------+
5755 + | Copyright (c) 2006 The PHP Group |
5756 + +----------------------------------------------------------------------+
5757 + | This source file is subject to version 3.01 of the PHP license, |
5758 + | that is bundled with this package in the file LICENSE, and is |
5759 + | available through the world-wide-web at the following url: |
5760 + | http://www.php.net/license/3_01.txt |
5761 + | If you did not receive a copy of the PHP license and are unable to |
5762 + | obtain it through the world-wide-web, please send a note to |
5763 + | license@php.net so we can mail you a copy immediately. |
5764 + +----------------------------------------------------------------------+
5765 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
5766 + | George Schlossnagle <george@omniti.com> |
5767 + | Rasmus Lerdorf <rasmus@php.net> |
5768 + | Arun C. Murthy <arunc@yahoo-inc.com> |
5769 + | Gopal Vijayaraghavan <gopalv@yahoo-inc.com> |
5770 + +----------------------------------------------------------------------+
5772 + This software was contributed to PHP by Community Connect Inc. in 2002
5773 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
5774 + Future revisions and derivatives of this source code must acknowledge
5775 + Community Connect Inc. as the original contributor of this module by
5776 + leaving this note intact in the source code.
5778 + All other licensing and usage conditions are those of the PHP Group.
5782 +/* $Id: apc.h,v 3.14 2007/03/17 14:01:41 gopalv Exp $ */
5788 + * This module defines utilities and helper functions used elsewhere in APC.
5791 +/* Commonly needed C library headers. */
5792 +#include <assert.h>
5794 +#include <stdarg.h>
5796 +#include <stdlib.h>
5797 +#include <string.h>
5800 +/* UNIX headers (needed for struct stat) */
5801 +#include <sys/types.h>
5802 +#include <sys/stat.h>
5804 +#include <unistd.h>
5807 +#ifdef HAVE_CONFIG_H
5808 +#include <config.h>
5813 +/* log levels constants (see apc_log) */
5814 +enum { APC_DBG, APC_NOTICE, APC_WARNING, APC_ERROR };
5816 +/* typedefs for extensible memory allocators */
5817 +typedef void* (*apc_malloc_t)(size_t);
5818 +typedef void (*apc_free_t) (void*);
5820 +/* wrappers for memory allocation routines */
5821 +extern void* apc_emalloc(size_t n);
5822 +extern void* apc_erealloc(void* p, size_t n);
5823 +extern void apc_efree(void* p);
5824 +extern char* apc_estrdup(const char* s);
5825 +extern void* apc_xstrdup(const char* s, apc_malloc_t f);
5826 +extern void* apc_xmemcpy(const void* p, size_t n, apc_malloc_t f);
5828 +/* console display functions */
5829 +extern void apc_log(int level, const char* fmt, ...);
5830 +extern void apc_eprint(const char* fmt, ...);
5831 +extern void apc_wprint(const char* fmt, ...);
5832 +extern void apc_dprint(const char* fmt, ...);
5833 +extern void apc_nprint(const char* fmt, ...);
5835 +/* string and text manipulation */
5836 +extern char* apc_append(const char* s, const char* t);
5837 +extern char* apc_substr(const char* s, int start, int length);
5838 +extern char** apc_tokenize(const char* s, char delim);
5840 +/* filesystem functions */
5842 +typedef struct apc_fileinfo_t
5844 + char fullpath[MAXPATHLEN+1];
5845 + struct stat st_buf;
5849 +#define apc_stat(f, b) stat(f, b)
5851 +#define apc_stat(f, b) apc_win32_stat(f, b TSRMLS_CC)
5852 +extern int apc_win32_stat(const char *path, struct stat *buf TSRMLS_DC);
5854 +extern int apc_search_paths(const char* filename, const char* path, apc_fileinfo_t* fileinfo);
5856 +/* regular expression wrapper functions */
5857 +extern void* apc_regex_compile_array(char* patterns[]);
5858 +extern void apc_regex_destroy_array(void* p);
5859 +extern int apc_regex_match_array(void* p, const char* input);
5861 +/* apc_crc32: returns the CRC-32 checksum of the first len bytes in buf */
5862 +extern unsigned int apc_crc32(const char* buf, int len);
5864 +#define APC_NEGATIVE_MATCH 1
5865 +#define APC_POSITIVE_MATCH 2
5870 + * Local variables:
5872 + * c-basic-offset: 4
5874 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
5875 + * vim<600: expandtab sw=4 ts=4 sts=4
5877 diff -ruN php-5.1.6.old/ext/apc/apc_lock.h php-5.1.6/ext/APC/apc_lock.h
5878 --- php-5.1.6.old/ext/apc/apc_lock.h 1969-12-31 18:00:00.000000000 -0600
5879 +++ php-5.1.6/ext/apc/apc_lock.h 2007-04-02 18:05:30.000000000 -0500
5882 + +----------------------------------------------------------------------+
5884 + +----------------------------------------------------------------------+
5885 + | Copyright (c) 2006 The PHP Group |
5886 + +----------------------------------------------------------------------+
5887 + | This source file is subject to version 3.01 of the PHP license, |
5888 + | that is bundled with this package in the file LICENSE, and is |
5889 + | available through the world-wide-web at the following url: |
5890 + | http://www.php.net/license/3_01.txt |
5891 + | If you did not receive a copy of the PHP license and are unable to |
5892 + | obtain it through the world-wide-web, please send a note to |
5893 + | license@php.net so we can mail you a copy immediately. |
5894 + +----------------------------------------------------------------------+
5895 + | Authors: George Schlossnagle <george@omniti.com> |
5896 + | Rasmus Lerdorf <rasmus@php.net> |
5897 + +----------------------------------------------------------------------+
5899 + This software was contributed to PHP by Community Connect Inc. in 2002
5900 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
5901 + Future revisions and derivatives of this source code must acknowledge
5902 + Community Connect Inc. as the original contributor of this module by
5903 + leaving this note intact in the source code.
5905 + All other licensing and usage conditions are those of the PHP Group.
5909 +/* $Id: apc_lock.h,v 3.20 2007/01/29 07:39:02 shire Exp $ */
5914 +#include "apc_sem.h"
5915 +#include "apc_fcntl.h"
5916 +#include "apc_pthreadmutex.h"
5917 +#include "apc_futex.h"
5918 +#include "apc_spin.h"
5919 +#ifdef HAVE_CONFIG_H
5920 +#include <config.h>
5924 +#define RDLOCK_AVAILABLE 0
5925 +#define NONBLOCKING_LOCK_AVAILABLE 0
5926 +/* quick & dirty: use TSRM mutex locks for now */
5927 +#define apc_lck_create(a,b,c,d) d=(int)tsrm_mutex_alloc()
5928 +#define apc_lck_destroy(a) tsrm_mutex_free((MUTEX_T)a)
5929 +#define apc_lck_lock(a) tsrm_mutex_lock((MUTEX_T)a)
5930 +#define apc_lck_rdlock(a) tsrm_mutex_lock((MUTEX_T)a)
5931 +#define apc_lck_unlock(a) tsrm_mutex_unlock((MUTEX_T)a)
5932 +#elif defined(APC_SEM_LOCKS)
5933 +#define RDLOCK_AVAILABLE 0
5934 +#define NONBLOCKING_LOCK_AVAILABLE 0
5935 +#define apc_lck_t int
5936 +#define apc_lck_create(a,b,c,d) d=apc_sem_create(NULL,(b),(c))
5937 +#define apc_lck_destroy(a) apc_sem_destroy(a)
5938 +#define apc_lck_lock(a) apc_sem_lock(a)
5939 +#define apc_lck_rdlock(a) apc_sem_lock(a)
5940 +#define apc_lck_unlock(a) apc_sem_unlock(a)
5941 +#elif defined(APC_PTHREADMUTEX_LOCKS)
5942 +#define RDLOCK_AVAILABLE 0
5943 +#define NONBLOCKING_LOCK_AVAILABLE 1
5944 +#define apc_lck_t pthread_mutex_t
5945 +#define apc_lck_create(a,b,c,d) apc_pthreadmutex_create((pthread_mutex_t*)&d)
5946 +#define apc_lck_destroy(a) apc_pthreadmutex_destroy(&a)
5947 +#define apc_lck_lock(a) apc_pthreadmutex_lock(&a)
5948 +#define apc_lck_nb_lock(a) apc_pthreadmutex_nonblocking_lock(&a)
5949 +#define apc_lck_rdlock(a) apc_pthreadmutex_lock(&a)
5950 +#define apc_lck_unlock(a) apc_pthreadmutex_unlock(&a)
5951 +#elif defined(APC_FUTEX_LOCKS)
5952 +#define NONBLOCKING_LOCK_AVAILABLE 1
5953 +#define apc_lck_t int
5954 +#define apc_lck_create(a,b,c,d) d=apc_futex_create()
5955 +#define apc_lck_destroy(a) apc_futex_destroy(&a)
5956 +#define apc_lck_lock(a) apc_futex_lock(&a)
5957 +#define apc_lck_nb_lock(a) apc_futex_nonblocking_lock(&a)
5958 +#define apc_lck_rdlock(a) apc_futex_lock(&a)
5959 +#define apc_lck_unlock(a) apc_futex_unlock(&a)
5960 +#elif defined(APC_SPIN_LOCKS)
5961 +#define NONBLOCKING_LOCK_AVAILABLE APC_SLOCK_NONBLOCKING_LOCK_AVAILABLE
5962 +#define apc_lck_t slock_t
5963 +#define apc_lck_create(a,b,c,d) apc_slock_create((slock_t*)&(d))
5964 +#define apc_lck_destroy(a) apc_slock_destroy(&a)
5965 +#define apc_lck_lock(a) apc_slock_lock(&a)
5966 +#define apc_lck_nb_lock(a) apc_slock_nonblocking_lock(&a)
5967 +#define apc_lck_rdlock(a) apc_slock_lock(&a)
5968 +#define apc_lck_unlock(a) apc_slock_unlock(&a)
5970 +#define RDLOCK_AVAILABLE 1
5972 +#define NONBLOCKING_LOCK_AVAILABLE 0
5974 +#define NONBLOCKING_LOCK_AVAILABLE 1
5976 +#define apc_lck_t int
5977 +#define apc_lck_create(a,b,c,d) d=apc_fcntl_create((a))
5978 +#define apc_lck_destroy(a) apc_fcntl_destroy(a)
5979 +#define apc_lck_lock(a) apc_fcntl_lock(a)
5980 +#define apc_lck_nb_lock(a) apc_fcntl_nonblocking_lock(a)
5981 +#define apc_lck_rdlock(a) apc_fcntl_rdlock(a)
5982 +#define apc_lck_unlock(a) apc_fcntl_unlock(a)
5986 diff -ruN php-5.1.6.old/ext/apc/apc_main.c php-5.1.6/ext/APC/apc_main.c
5987 --- php-5.1.6.old/ext/apc/apc_main.c 1969-12-31 18:00:00.000000000 -0600
5988 +++ php-5.1.6/ext/apc/apc_main.c 2007-04-02 18:05:30.000000000 -0500
5991 + +----------------------------------------------------------------------+
5993 + +----------------------------------------------------------------------+
5994 + | Copyright (c) 2006 The PHP Group |
5995 + +----------------------------------------------------------------------+
5996 + | This source file is subject to version 3.01 of the PHP license, |
5997 + | that is bundled with this package in the file LICENSE, and is |
5998 + | available through the world-wide-web at the following url: |
5999 + | http://www.php.net/license/3_01.txt |
6000 + | If you did not receive a copy of the PHP license and are unable to |
6001 + | obtain it through the world-wide-web, please send a note to |
6002 + | license@php.net so we can mail you a copy immediately. |
6003 + +----------------------------------------------------------------------+
6004 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
6005 + | Rasmus Lerdorf <rasmus@php.net> |
6006 + | Arun C. Murthy <arunc@yahoo-inc.com> |
6007 + | Gopal Vijayaraghavan <gopalv@yahoo-inc.com> |
6008 + +----------------------------------------------------------------------+
6010 + This software was contributed to PHP by Community Connect Inc. in 2002
6011 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
6012 + Future revisions and derivatives of this source code must acknowledge
6013 + Community Connect Inc. as the original contributor of this module by
6014 + leaving this note intact in the source code.
6016 + All other licensing and usage conditions are those of the PHP Group.
6020 +/* $Id: apc_main.c,v 3.97 2007/03/22 16:03:59 gopalv Exp $ */
6022 +#include "apc_php.h"
6023 +#include "apc_main.h"
6025 +#include "apc_lock.h"
6026 +#include "apc_cache.h"
6027 +#include "apc_compile.h"
6028 +#include "apc_globals.h"
6029 +#include "apc_sma.h"
6030 +#include "apc_stack.h"
6031 +#include "apc_zend.h"
6033 +#if PHP_API_VERSION <= 20020918
6035 +#ifdef APC_PHP4_STAT
6042 +/* {{{ module variables */
6044 +/* pointer to the original Zend engine compile_file function */
6045 +typedef zend_op_array* (zend_compile_t)(zend_file_handle*, int TSRMLS_DC);
6046 +static zend_compile_t *old_compile_file;
6050 +/* {{{ get/set old_compile_file (to interact with other extensions that need the compile hook) */
6051 +static zend_compile_t* set_compile_hook(zend_compile_t *ptr)
6053 + zend_compile_t *retval = old_compile_file;
6055 + if (ptr != NULL) old_compile_file = ptr;
6060 +/* {{{ install_function */
6061 +static int install_function(apc_function_t fn TSRMLS_DC)
6064 + zend_hash_add(EG(function_table),
6067 + apc_copy_function_for_execution(fn.function),
6068 + sizeof(fn.function[0]),
6071 + if (status == FAILURE) {
6072 + /* apc_eprint("Cannot redeclare %s()", fn.name); */
6079 +/* {{{ install_class */
6080 +static int install_class(apc_class_t cl TSRMLS_DC)
6082 + zend_class_entry* class_entry = cl.class_entry;
6083 + zend_class_entry* parent = NULL;
6085 +#ifdef ZEND_ENGINE_2
6086 + zend_class_entry** allocated_ce = NULL;
6090 + /* Special case for mangled names. Mangled names are unique to a file.
6091 + * There is no way two classes with the same mangled name will occur,
6092 + * unless a file is included twice. And if in case, a file is included
6093 + * twice, all mangled name conflicts can be ignored and the class redeclaration
6094 + * error may be deferred till runtime of the corresponding DECLARE_CLASS
6098 + if(cl.name_len != 0 && cl.name[0] == '\0') {
6099 + if(zend_hash_exists(CG(class_table), cl.name, cl.name_len+1)) {
6104 +#ifdef ZEND_ENGINE_2
6106 + * XXX: We need to free this somewhere...
6108 + allocated_ce = apc_php_malloc(sizeof(zend_class_entry*));
6110 + if(!allocated_ce) {
6117 + apc_copy_class_entry_for_execution(cl.class_entry,
6121 + /* restore parent class pointer for compile-time inheritance */
6122 + if (cl.parent_name != NULL) {
6123 +#ifdef ZEND_ENGINE_2
6124 + zend_class_entry** parent_ptr = NULL;
6126 + * zend_lookup_class has to be due to presence of __autoload,
6127 + * just looking up the EG(class_table) is not enough in php5!
6128 + * Even more dangerously, thanks to __autoload and people using
6129 + * class names as filepaths for inclusion, this has to be case
6130 + * sensitive. zend_lookup_class automatically does a case_fold
6131 + * internally, but passes the case preserved version to __autoload.
6132 + * Aside: Do NOT pass *strlen(cl.parent_name)+1* because
6133 + * zend_lookup_class does it internally anyway!
6135 + status = zend_lookup_class(cl.parent_name,
6136 + strlen(cl.parent_name),
6137 + &parent_ptr TSRMLS_CC);
6139 + status = zend_hash_find(EG(class_table),
6141 + strlen(cl.parent_name)+1,
6142 + (void**) &parent);
6144 + if (status == FAILURE) {
6145 + if(APCG(report_autofilter)) {
6146 + apc_wprint("Dynamic inheritance detected for class %s", cl.name);
6148 + class_entry->parent = NULL;
6152 +#ifdef ZEND_ENGINE_2
6153 + parent = *parent_ptr;
6155 + class_entry->parent = parent;
6156 +#ifdef ZEND_ENGINE_2
6157 + zend_do_inheritance(class_entry, parent TSRMLS_CC);
6159 + zend_do_inheritance(class_entry, parent);
6166 +#ifdef ZEND_ENGINE_2
6167 + status = zend_hash_add(EG(class_table),
6171 + sizeof(zend_class_entry*),
6174 + status = zend_hash_add(EG(class_table),
6178 + sizeof(zend_class_entry),
6182 + if (status == FAILURE) {
6183 + apc_eprint("Cannot redeclare class %s", cl.name);
6189 +/* {{{ uninstall_class */
6190 +static int uninstall_class(apc_class_t cl TSRMLS_DC)
6194 +#ifdef ZEND_ENGINE_2
6195 + status = zend_hash_del(EG(class_table),
6199 + status = zend_hash_del(EG(class_table),
6203 + if (status == FAILURE) {
6204 + apc_eprint("Cannot delete class %s", cl.name);
6210 +/* {{{ compare_file_handles */
6211 +static int compare_file_handles(void* a, void* b)
6213 + zend_file_handle* fh1 = (zend_file_handle*)a;
6214 + zend_file_handle* fh2 = (zend_file_handle*)b;
6215 + return (fh1->type == fh2->type &&
6216 + fh1->filename == fh2->filename &&
6217 + fh1->opened_path == fh2->opened_path);
6221 +/* {{{ cached_compile */
6222 +static zend_op_array* cached_compile(zend_file_handle* h,
6223 + int type TSRMLS_DC)
6225 + apc_cache_entry_t* cache_entry;
6228 + cache_entry = (apc_cache_entry_t*) apc_stack_top(APCG(cache_stack));
6229 + assert(cache_entry != NULL);
6231 + if (cache_entry->data.file.classes) {
6232 + for (i = 0; cache_entry->data.file.classes[i].class_entry != NULL; i++) {
6233 + if(install_class(cache_entry->data.file.classes[i] TSRMLS_CC) == FAILURE) {
6234 + goto default_compile;
6239 + if (cache_entry->data.file.functions) {
6240 + for (i = 0; cache_entry->data.file.functions[i].function != NULL; i++) {
6241 + install_function(cache_entry->data.file.functions[i] TSRMLS_CC);
6246 + return apc_copy_op_array_for_execution(NULL, cache_entry->data.file.op_array TSRMLS_CC);
6250 + cache_entry->autofiltered = 1;
6251 + if(APCG(report_autofilter)) {
6252 + apc_wprint("Autofiltering %s", h->opened_path);
6255 + if(cache_entry->data.file.classes) {
6256 + for(ii = 0; ii < i ; ii++) {
6257 + uninstall_class(cache_entry->data.file.classes[ii] TSRMLS_CC);
6261 + apc_stack_pop(APCG(cache_stack)); /* pop out cache_entry */
6263 + /* cannot free up cache data yet, it maybe in use */
6265 + zend_llist_del_element(&CG(open_files), h, compare_file_handles); /* XXX: kludge */
6267 + h->type = ZEND_HANDLE_FILENAME;
6269 + return old_compile_file(h, type TSRMLS_CC);
6273 +/* {{{ my_compile_file
6274 + Overrides zend_compile_file */
6275 +static zend_op_array* my_compile_file(zend_file_handle* h,
6276 + int type TSRMLS_DC)
6278 + apc_cache_key_t key;
6279 + apc_cache_entry_t* cache_entry;
6280 + zend_op_array* op_array;
6281 + int num_functions, num_classes, ret;
6282 + zend_op_array* alloc_op_array;
6283 + apc_function_t* alloc_functions;
6284 + apc_class_t* alloc_classes;
6289 + if (!APCG(enabled) || (apc_cache_busy(apc_cache) && !APCG(localcache))) {
6290 + return old_compile_file(h, type TSRMLS_CC);
6293 + /* check our regular expression filters */
6294 + if (APCG(filters) && apc_compiled_filters) {
6295 + int ret = apc_regex_match_array(apc_compiled_filters, h->filename);
6296 + if(ret == APC_NEGATIVE_MATCH || (ret != APC_POSITIVE_MATCH && !APCG(cache_by_default))) {
6297 + return old_compile_file(h, type TSRMLS_CC);
6299 + } else if(!APCG(cache_by_default)) {
6300 + return old_compile_file(h, type TSRMLS_CC);
6303 +#if PHP_API_VERSION <= 20041225
6304 +#if HAVE_APACHE && defined(APC_PHP4_STAT)
6305 + t = ((request_rec *)SG(server_context))->request_time;
6310 + t = sapi_get_request_time(TSRMLS_C);
6313 +#ifdef __DEBUG_APC__
6314 + fprintf(stderr,"1. h->opened_path=[%s] h->filename=[%s]\n", h->opened_path?h->opened_path:"null",h->filename);
6317 + /* try to create a cache key; if we fail, give up on caching */
6318 + if (!apc_cache_make_file_key(&key, h->filename, PG(include_path), t TSRMLS_CC)) {
6319 + return old_compile_file(h, type TSRMLS_CC);
6322 + if(APCG(localcache)) {
6323 + /* search for the file in the local cache */
6324 + cache_entry = apc_local_cache_find(APCG(lcache), key, t);
6326 + /* search for the file in the cache */
6327 + cache_entry = apc_cache_find(apc_cache, key, t);
6330 + if (cache_entry != NULL && !cache_entry->autofiltered) {
6332 + if (h->opened_path == NULL) {
6333 + h->opened_path = estrdup(cache_entry->data.file.filename);
6335 + zend_hash_add(&EG(included_files), h->opened_path, strlen(h->opened_path)+1, (void *)&dummy, sizeof(int), NULL);
6336 + zend_llist_add_element(&CG(open_files), h); /* XXX kludge */
6337 + apc_stack_push(APCG(cache_stack), cache_entry);
6338 + return cached_compile(h, type TSRMLS_CC);
6340 + else if(cache_entry != NULL && cache_entry->autofiltered) {
6341 + /* nobody else is using this cache_entry */
6342 + if(cache_entry->ref_count == 1) {
6343 + if(cache_entry->data.file.op_array) {
6344 + apc_free_op_array(cache_entry->data.file.op_array, apc_sma_free);
6345 + cache_entry->data.file.op_array = NULL;
6347 + if(cache_entry->data.file.functions) {
6348 + apc_free_functions(cache_entry->data.file.functions, apc_sma_free);
6349 + cache_entry->data.file.functions = NULL;
6351 + if(cache_entry->data.file.classes) {
6352 + apc_free_classes(cache_entry->data.file.classes, apc_sma_free);
6353 + cache_entry->data.file.classes = NULL;
6356 + /* We never push this into the cache_stack, so we have to do a release */
6357 + apc_cache_release(apc_cache, cache_entry);
6358 + return old_compile_file(h, type TSRMLS_CC);
6361 + if(apc_cache_busy(apc_cache) && APCG(localcache)) {
6362 + /* possibly local cache returned NULL because cache is busy */
6363 + return old_compile_file(h, type TSRMLS_CC);
6366 + /* remember how many functions and classes existed before compilation */
6367 + num_functions = zend_hash_num_elements(CG(function_table));
6368 + num_classes = zend_hash_num_elements(CG(class_table));
6370 + /* compile the file using the default compile function */
6371 + op_array = old_compile_file(h, type TSRMLS_CC);
6372 + if (op_array == NULL) {
6376 + * Basically this will cause a file only to be cached on a percentage
6377 + * of the attempts. This is to avoid cache slams when starting up a
6378 + * very busy server or when modifying files on a very busy live server.
6379 + * There is no point having many processes all trying to cache the same
6380 + * file at the same time. By introducing a chance of being cached
6381 + * we theoretically cut the cache slam problem by the given percentage.
6382 + * For example if apc.slam_defense is set to 66 then 2/3 of the attempts
6383 + * to cache an uncached file will be ignored.
6385 + if(APCG(slam_defense)) {
6386 + if(APCG(slam_rand)==-1) {
6387 + APCG(slam_rand) = (int)(100.0*rand()/(RAND_MAX+1.0));
6389 + if(APCG(slam_rand) < APCG(slam_defense)) {
6394 + HANDLE_BLOCK_INTERRUPTIONS();
6396 +#if NONBLOCKING_LOCK_AVAILABLE
6397 + if(APCG(write_lock)) {
6398 + if(!apc_cache_write_lock(apc_cache)) {
6399 + HANDLE_UNBLOCK_INTERRUPTIONS();
6406 + APCG(mem_size_ptr) = &mem_size;
6407 + if(!(alloc_op_array = apc_copy_op_array(NULL, op_array, apc_sma_malloc, apc_sma_free TSRMLS_CC))) {
6408 + apc_cache_expunge(apc_cache,t);
6409 + apc_cache_expunge(apc_user_cache,t);
6410 + APCG(mem_size_ptr) = NULL;
6411 +#if NONBLOCKING_LOCK_AVAILABLE
6412 + if(APCG(write_lock)) {
6413 + apc_cache_write_unlock(apc_cache);
6416 + HANDLE_UNBLOCK_INTERRUPTIONS();
6420 + if(!(alloc_functions = apc_copy_new_functions(num_functions, apc_sma_malloc, apc_sma_free TSRMLS_CC))) {
6421 + apc_free_op_array(alloc_op_array, apc_sma_free);
6422 + apc_cache_expunge(apc_cache,t);
6423 + apc_cache_expunge(apc_user_cache,t);
6424 + APCG(mem_size_ptr) = NULL;
6425 +#if NONBLOCKING_LOCK_AVAILABLE
6426 + if(APCG(write_lock)) {
6427 + apc_cache_write_unlock(apc_cache);
6430 + HANDLE_UNBLOCK_INTERRUPTIONS();
6433 + if(!(alloc_classes = apc_copy_new_classes(op_array, num_classes, apc_sma_malloc, apc_sma_free TSRMLS_CC))) {
6434 + apc_free_op_array(alloc_op_array, apc_sma_free);
6435 + apc_free_functions(alloc_functions, apc_sma_free);
6436 + apc_cache_expunge(apc_cache,t);
6437 + apc_cache_expunge(apc_user_cache,t);
6438 + APCG(mem_size_ptr) = NULL;
6439 +#if NONBLOCKING_LOCK_AVAILABLE
6440 + if(APCG(write_lock)) {
6441 + apc_cache_write_unlock(apc_cache);
6444 + HANDLE_UNBLOCK_INTERRUPTIONS();
6448 + path = h->opened_path;
6449 + if(!path) path=h->filename;
6451 +#ifdef __DEBUG_APC__
6452 + fprintf(stderr,"2. h->opened_path=[%s] h->filename=[%s]\n", h->opened_path?h->opened_path:"null",h->filename);
6455 + if(!(cache_entry = apc_cache_make_file_entry(path, alloc_op_array, alloc_functions, alloc_classes))) {
6456 + apc_free_op_array(alloc_op_array, apc_sma_free);
6457 + apc_free_functions(alloc_functions, apc_sma_free);
6458 + apc_free_classes(alloc_classes, apc_sma_free);
6459 + apc_cache_expunge(apc_cache,t);
6460 + apc_cache_expunge(apc_user_cache,t);
6461 + APCG(mem_size_ptr) = NULL;
6462 +#if NONBLOCKING_LOCK_AVAILABLE
6463 + if(APCG(write_lock)) {
6464 + apc_cache_write_unlock(apc_cache);
6467 + HANDLE_UNBLOCK_INTERRUPTIONS();
6470 + APCG(mem_size_ptr) = NULL;
6471 + cache_entry->mem_size = mem_size;
6473 + if ((ret = apc_cache_insert(apc_cache, key, cache_entry, t)) != 1) {
6474 + apc_cache_free_entry(cache_entry);
6476 + apc_cache_expunge(apc_cache,t);
6477 + apc_cache_expunge(apc_user_cache,t);
6481 +#if NONBLOCKING_LOCK_AVAILABLE
6482 + if(APCG(write_lock)) {
6483 + apc_cache_write_unlock(apc_cache);
6486 + HANDLE_UNBLOCK_INTERRUPTIONS();
6492 +/* {{{ module init and shutdown */
6494 +int apc_module_init(int module_number TSRMLS_DC)
6496 + /* apc initialization */
6498 + apc_sma_init(APCG(shm_segments), APCG(shm_size)*1024*1024, APCG(mmap_file_mask));
6500 + apc_sma_init(APCG(shm_segments), APCG(shm_size)*1024*1024, NULL);
6502 + apc_cache = apc_cache_create(APCG(num_files_hint), APCG(gc_ttl), APCG(ttl));
6503 + apc_user_cache = apc_cache_create(APCG(user_entries_hint), APCG(gc_ttl), APCG(user_ttl));
6505 + apc_compiled_filters = apc_regex_compile_array(APCG(filters));
6507 + /* override compilation */
6508 + old_compile_file = zend_compile_file;
6509 + zend_compile_file = my_compile_file;
6510 + REGISTER_LONG_CONSTANT("\000apc_magic", (long)&set_compile_hook, CONST_PERSISTENT | CONST_CS);
6512 + APCG(initialized) = 1;
6516 +int apc_module_shutdown(TSRMLS_D)
6518 + if (!APCG(initialized))
6521 + /* restore compilation */
6522 + zend_compile_file = old_compile_file;
6525 + * In case we got interrupted by a SIGTERM or something else during execution
6526 + * we may have cache entries left on the stack that we need to check to make
6527 + * sure that any functions or classes these may have added to the global function
6528 + * and class tables are removed before we blow away the memory that hold them.
6530 + * This is merely to remove memory leak warnings - as the process is terminated
6531 + * immediately after shutdown. The following while loop can be removed without
6532 + * affecting anything else.
6534 + while (apc_stack_size(APCG(cache_stack)) > 0) {
6536 + apc_cache_entry_t* cache_entry = (apc_cache_entry_t*) apc_stack_pop(APCG(cache_stack));
6537 + if (cache_entry->data.file.functions) {
6538 + for (i = 0; cache_entry->data.file.functions[i].function != NULL; i++) {
6539 + zend_hash_del(EG(function_table),
6540 + cache_entry->data.file.functions[i].name,
6541 + cache_entry->data.file.functions[i].name_len+1);
6544 + if (cache_entry->data.file.classes) {
6545 + for (i = 0; cache_entry->data.file.classes[i].class_entry != NULL; i++) {
6546 + zend_hash_del(EG(class_table),
6547 + cache_entry->data.file.classes[i].name,
6548 + cache_entry->data.file.classes[i].name_len+1);
6551 + apc_cache_release(apc_cache, cache_entry);
6554 + apc_cache_destroy(apc_cache);
6555 + apc_cache_destroy(apc_user_cache);
6556 + apc_sma_cleanup();
6558 + APCG(initialized) = 0;
6564 +/* {{{ process init and shutdown */
6565 +int apc_process_init(int module_number TSRMLS_DC)
6567 + int minttl = (APCG(gc_ttl) > APCG(ttl) ? APCG(ttl) : APCG(gc_ttl))/2;
6568 + int size = APCG(localcache_size);
6569 + if(APCG(initialized) && APCG(localcache)) {
6570 + /* TTL is 2 mins by default */
6571 + APCG(lcache) = apc_local_cache_create(apc_cache, size, minttl ? minttl : 120);
6576 +int apc_process_shutdown(TSRMLS_D)
6578 + if(APCG(initialized) && APCG(localcache) && APCG(lcache)) {
6579 + apc_local_cache_destroy(APCG(lcache));
6580 + APCG(lcache) = NULL;
6586 +/* {{{ request init and shutdown */
6588 +int apc_request_init(TSRMLS_D)
6590 + apc_stack_clear(APCG(cache_stack));
6591 + APCG(slam_rand) = -1;
6592 + APCG(copied_zvals) = NULL;
6596 +int apc_request_shutdown(TSRMLS_D)
6598 + apc_deactivate(TSRMLS_C);
6604 +/* {{{ apc_deactivate */
6605 +void apc_deactivate(TSRMLS_D)
6607 + /* The execution stack was unwound, which prevented us from decrementing
6608 + * the reference counts on active cache entries in `my_execute`.
6610 + while (apc_stack_size(APCG(cache_stack)) > 0) {
6612 + zend_class_entry* zce = NULL;
6613 + void ** centry = (void*)(&zce);
6614 +#ifdef ZEND_ENGINE_2
6615 + zend_class_entry** pzce = NULL;
6618 + apc_cache_entry_t* cache_entry =
6619 + (apc_cache_entry_t*) apc_stack_pop(APCG(cache_stack));
6621 + if (cache_entry->data.file.functions) {
6622 + for (i = 0; cache_entry->data.file.functions[i].function != NULL; i++) {
6623 + zend_hash_del(EG(function_table),
6624 + cache_entry->data.file.functions[i].name,
6625 + cache_entry->data.file.functions[i].name_len+1);
6629 + if (cache_entry->data.file.classes) {
6630 + for (i = 0; cache_entry->data.file.classes[i].class_entry != NULL; i++) {
6631 +#ifdef ZEND_ENGINE_2
6632 + centry = (void**)&pzce; /* a triple indirection to get zend_class_entry*** */
6634 + if(zend_hash_find(EG(class_table),
6635 + cache_entry->data.file.classes[i].name,
6636 + cache_entry->data.file.classes[i].name_len+1,
6637 + (void**)centry) == FAILURE)
6639 + /* double inclusion of conditional classes ends up failing
6640 + * this lookup the second time around.
6645 +#ifdef ZEND_ENGINE_2
6648 + zend_hash_del(EG(class_table),
6649 + cache_entry->data.file.classes[i].name,
6650 + cache_entry->data.file.classes[i].name_len+1);
6652 + apc_free_class_entry_after_execution(zce);
6655 + apc_cache_release(apc_cache, cache_entry);
6657 + if(APCG(localcache)) {
6658 + apc_local_cache_cleanup(APCG(lcache));
6664 + * Local variables:
6666 + * c-basic-offset: 4
6668 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
6669 + * vim<600: expandtab sw=4 ts=4 sts=4
6671 diff -ruN php-5.1.6.old/ext/apc/apc_main.h php-5.1.6/ext/APC/apc_main.h
6672 --- php-5.1.6.old/ext/apc/apc_main.h 1969-12-31 18:00:00.000000000 -0600
6673 +++ php-5.1.6/ext/apc/apc_main.h 2007-04-02 18:05:30.000000000 -0500
6676 + +----------------------------------------------------------------------+
6678 + +----------------------------------------------------------------------+
6679 + | Copyright (c) 2006 The PHP Group |
6680 + +----------------------------------------------------------------------+
6681 + | This source file is subject to version 3.01 of the PHP license, |
6682 + | that is bundled with this package in the file LICENSE, and is |
6683 + | available through the world-wide-web at the following url: |
6684 + | http://www.php.net/license/3_01.txt |
6685 + | If you did not receive a copy of the PHP license and are unable to |
6686 + | obtain it through the world-wide-web, please send a note to |
6687 + | license@php.net so we can mail you a copy immediately. |
6688 + +----------------------------------------------------------------------+
6689 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
6690 + | George Schlossnagle <george@omniti.com> |
6691 + | Rasmus Lerdorf <rasmus@php.net> |
6692 + | Arun C. Murthy <arunc@yahoo-inc.com> |
6693 + | Gopal Vijayaraghavan <gopalv@yahoo-inc.com> |
6694 + +----------------------------------------------------------------------+
6696 + This software was contributed to PHP by Community Connect Inc. in 2002
6697 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
6698 + Future revisions and derivatives of this source code must acknowledge
6699 + Community Connect Inc. as the original contributor of this module by
6700 + leaving this note intact in the source code.
6702 + All other licensing and usage conditions are those of the PHP Group.
6706 +/* $Id: apc_main.h,v 3.9 2007/02/28 01:15:18 gopalv Exp $ */
6712 + * This module provides the primary interface between PHP and APC.
6715 +extern int apc_module_init(int module_number TSRMLS_DC);
6716 +extern int apc_module_shutdown(TSRMLS_D);
6717 +extern int apc_process_init(int module_number TSRMLS_DC);
6718 +extern int apc_process_shutdown(TSRMLS_D);
6719 +extern int apc_request_init(TSRMLS_D);
6720 +extern int apc_request_shutdown(TSRMLS_D);
6723 + * apc_deactivate is called by the PHP interpreter when an "exception" is
6724 + * raised (e.g., a call to the exit function) that unwinds the execution
6727 +extern void apc_deactivate();
6730 +extern const char* apc_version();
6735 + * Local variables:
6737 + * c-basic-offset: 4
6739 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
6740 + * vim<600: expandtab sw=4 ts=4 sts=4
6742 diff -ruN php-5.1.6.old/ext/apc/apc_mmap.c php-5.1.6/ext/APC/apc_mmap.c
6743 --- php-5.1.6.old/ext/apc/apc_mmap.c 1969-12-31 18:00:00.000000000 -0600
6744 +++ php-5.1.6/ext/apc/apc_mmap.c 2007-04-02 18:05:30.000000000 -0500
6747 + +----------------------------------------------------------------------+
6749 + +----------------------------------------------------------------------+
6750 + | Copyright (c) 2006 The PHP Group |
6751 + +----------------------------------------------------------------------+
6752 + | This source file is subject to version 3.01 of the PHP license, |
6753 + | that is bundled with this package in the file LICENSE, and is |
6754 + | available through the world-wide-web at the following url: |
6755 + | http://www.php.net/license/3_01.txt |
6756 + | If you did not receive a copy of the PHP license and are unable to |
6757 + | obtain it through the world-wide-web, please send a note to |
6758 + | license@php.net so we can mail you a copy immediately. |
6759 + +----------------------------------------------------------------------+
6760 + | Authors: Rasmus Lerdorf <rasmus@php.net> |
6761 + +----------------------------------------------------------------------+
6763 + This software was contributed to PHP by Community Connect Inc. in 2002
6764 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
6765 + Future revisions and derivatives of this source code must acknowledge
6766 + Community Connect Inc. as the original contributor of this module by
6767 + leaving this note intact in the source code.
6769 + All other licensing and usage conditions are those of the PHP Group.
6773 +/* $Id: apc_mmap.c,v 3.5 2006/03/12 00:31:45 rasmus Exp $ */
6780 +#include <sys/types.h>
6781 +#include <sys/mman.h>
6784 + * Some operating systems (like FreeBSD) have a MAP_NOSYNC flag that
6785 + * tells whatever update daemons might be running to not flush dirty
6786 + * vm pages to disk unless absolutely necessary. My guess is that
6787 + * most systems that don't have this probably default to only synching
6788 + * to disk when absolutely necessary.
6791 +#define MAP_NOSYNC 0
6794 +void *apc_mmap(char *file_mask, int size)
6796 + void* shmaddr; /* the shared memory address */
6798 + /* If no filename was provided, do an anonymous mmap */
6799 + if(!file_mask || (file_mask && !strlen(file_mask))) {
6800 + shmaddr = (void *)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
6805 + * If the filemask contains .shm we try to do a POSIX-compliant shared memory
6806 + * backed mmap which should avoid synchs on some platforms. At least on
6807 + * FreeBSD this implies MAP_NOSYNC and on Linux it is equivalent of mmap'ing
6808 + * a file in a mounted shmfs. For this to work on Linux you need to make sure
6809 + * you actually have shmfs mounted. Also on Linux, make sure the file_mask you
6810 + * pass in has a leading / and no other /'s. eg. /apc.shm.XXXXXX
6811 + * On FreeBSD these are mapped onto the regular filesystem so you can put whatever
6812 + * path you want here.
6814 + if(strstr(file_mask,".shm")) {
6815 + mktemp(file_mask);
6816 + fd = shm_open(file_mask, O_CREAT|O_RDWR, S_IRUSR|S_IWUSR);
6818 + apc_eprint("apc_mmap: shm_open on %s failed:", file_mask);
6819 + return (void *)-1;
6821 + if (ftruncate(fd, size) < 0) {
6823 + shm_unlink(file_mask);
6824 + apc_eprint("apc_mmap: ftruncate failed:");
6825 + return (void *)-1;
6827 + shmaddr = (void *)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
6828 + shm_unlink(file_mask);
6832 + * Support anonymous mmap through the /dev/zero interface as well
6834 + else if(!strcmp(file_mask,"/dev/zero")) {
6835 + fd = open("/dev/zero", O_RDWR, S_IRUSR | S_IWUSR);
6837 + apc_eprint("apc_mmap: open on /dev/zero failed:");
6838 + return (void *)-1;
6840 + shmaddr = (void *)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
6844 + * Otherwise we do a normal filesystem mmap
6847 + fd = mkstemp(file_mask);
6849 + apc_eprint("apc_mmap: mkstemp on %s failed:", file_mask);
6850 + return (void *)-1;
6852 + if (ftruncate(fd, size) < 0) {
6854 + unlink(file_mask);
6855 + apc_eprint("apc_mmap: ftruncate failed:");
6857 + shmaddr = (void *)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_NOSYNC, fd, 0);
6859 + unlink(file_mask);
6862 + if((int)shmaddr == -1) {
6863 + apc_eprint("apc_mmap: mmap failed:");
6868 +void apc_unmap(void* shmaddr, int size)
6870 + munmap(shmaddr, size);
6876 + * Local variables:
6878 + * c-basic-offset: 4
6880 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
6881 + * vim<600: expandtab sw=4 ts=4 sts=4
6883 diff -ruN php-5.1.6.old/ext/apc/apc.php php-5.1.6/ext/APC/apc.php
6884 --- php-5.1.6.old/ext/apc/apc.php 1969-12-31 18:00:00.000000000 -0600
6885 +++ php-5.1.6/ext/apc/apc.php 2007-04-02 18:05:30.000000000 -0500
6889 + +----------------------------------------------------------------------+
6891 + +----------------------------------------------------------------------+
6892 + | Copyright (c) 2006 The PHP Group |
6893 + +----------------------------------------------------------------------+
6894 + | This source file is subject to version 3.01 of the PHP license, |
6895 + | that is bundled with this package in the file LICENSE, and is |
6896 + | available through the world-wide-web at the following url: |
6897 + | http://www.php.net/license/3_01.txt |
6898 + | If you did not receive a copy of the PHP license and are unable to |
6899 + | obtain it through the world-wide-web, please send a note to |
6900 + | license@php.net so we can mail you a copy immediately. |
6901 + +----------------------------------------------------------------------+
6902 + | Authors: Ralf Becker <beckerr@php.net> |
6903 + | Rasmus Lerdorf <rasmus@php.net> |
6904 + | Ilia Alshanetsky <ilia@prohost.org> |
6905 + +----------------------------------------------------------------------+
6907 + All other licensing and usage conditions are those of the PHP Group.
6911 +$VERSION='$Id: apc.php,v 3.65 2006/10/27 18:32:52 shire Exp $';
6913 +////////// READ OPTIONAL CONFIGURATION FILE ////////////
6914 +if (file_exists("apc.conf.php")) include("apc.conf.php");
6915 +////////////////////////////////////////////////////////
6917 +////////// BEGIN OF DEFAULT CONFIG AREA ///////////////////////////////////////////////////////////
6919 +defaults('USE_AUTHENTICATION',1); // Use (internal) authentication - best choice if
6920 + // no other authentication is available
6922 + // There will be no further authentication. You
6923 + // will have to handle this by yourself!
6925 + // You need to change ADMIN_PASSWORD to make
6927 +defaults('ADMIN_USERNAME','apc'); // Admin Username
6928 +defaults('ADMIN_PASSWORD','password'); // Admin Password - CHANGE THIS TO ENABLE!!!
6930 +// (beckerr) I'm using a clear text password here, because I've no good idea how to let
6931 +// users generate a md5 or crypt password in a easy way to fill it in above
6933 +//defaults('DATE_FORMAT', "d.m.Y H:i:s"); // German
6934 +defaults('DATE_FORMAT', 'Y/m/d H:i:s'); // US
6936 +defaults('GRAPH_SIZE',200); // Image size
6938 +////////// END OF DEFAULT CONFIG AREA /////////////////////////////////////////////////////////////
6941 +// "define if not defined"
6942 +function defaults($d,$v) {
6943 + if (!defined($d)) define($d,$v); // or just @define(...)
6946 +// rewrite $PHP_SELF to block XSS attacks
6948 +$PHP_SELF= isset($_SERVER['PHP_SELF']) ? htmlentities(strip_tags($_SERVER['PHP_SELF'],'')) : '';
6950 +$host = getenv('HOSTNAME');
6951 +if($host) { $host = '('.$host.')'; }
6953 +// operation constants
6954 +define('OB_HOST_STATS',1);
6955 +define('OB_SYS_CACHE',2);
6956 +define('OB_USER_CACHE',3);
6957 +define('OB_SYS_CACHE_DIR',4);
6958 +define('OB_VERSION_CHECK',9);
6960 +// check validity of input variables
6962 + 'OB' => '/^\d+$/', // operational mode switch
6963 + 'CC' => '/^[01]$/', // clear cache requested
6964 + 'SH' => '/^[a-z0-9]+$/', // shared object description
6966 + 'IMG' => '/^[123]$/', // image to generate
6967 + 'LO' => '/^1$/', // login requested
6969 + 'COUNT' => '/^\d+$/', // number of line displayed in list
6970 + 'SCOPE' => '/^[AD]$/', // list view scope
6971 + 'SORT1' => '/^[AHSMCDTZ]$/', // first sort key
6972 + 'SORT2' => '/^[DA]$/', // second sort key
6973 + 'AGGR' => '/^\d+$/', // aggregation by dir level
6974 + 'SEARCH' => '/^.*$/' // aggregation by dir level
6977 +// default cache mode
6978 +$cache_mode='opcode';
6982 + 'A' => 'cache_list',
6983 + 'D' => 'deleted_list'
6986 +// handle POST and GET requests
6987 +if (empty($_REQUEST)) {
6988 + if (!empty($_GET) && !empty($_POST)) {
6989 + $_REQUEST = array_merge($_GET, $_POST);
6990 + } else if (!empty($_GET)) {
6991 + $_REQUEST = $_GET;
6992 + } else if (!empty($_POST)) {
6993 + $_REQUEST = $_POST;
6995 + $_REQUEST = array();
6999 +// check parameter syntax
7000 +foreach($vardom as $var => $dom) {
7001 + if (!isset($_REQUEST[$var])) {
7002 + $MYREQUEST[$var]=NULL;
7003 + } else if (!is_array($_REQUEST[$var]) && preg_match($dom,$_REQUEST[$var])) {
7004 + $MYREQUEST[$var]=$_REQUEST[$var];
7006 + $MYREQUEST[$var]=$_REQUEST[$var]=NULL;
7010 +// check parameter sematics
7011 +if (empty($MYREQUEST['SCOPE'])) $MYREQUEST['SCOPE']="A";
7012 +if (empty($MYREQUEST['SORT1'])) $MYREQUEST['SORT1']="H";
7013 +if (empty($MYREQUEST['SORT2'])) $MYREQUEST['SORT2']="D";
7014 +if (empty($MYREQUEST['OB'])) $MYREQUEST['OB']=OB_HOST_STATS;
7015 +if (!isset($MYREQUEST['COUNT'])) $MYREQUEST['COUNT']=20;
7016 +if (!isset($scope_list[$MYREQUEST['SCOPE']])) $MYREQUEST['SCOPE']='A';
7020 + "?SCOPE=".$MYREQUEST['SCOPE'].
7021 + "&SORT1=".$MYREQUEST['SORT1'].
7022 + "&SORT2=".$MYREQUEST['SORT2'].
7023 + "&COUNT=".$MYREQUEST['COUNT'];
7026 + "?SCOPE=".$MYREQUEST['SCOPE'].
7027 + "&COUNT=".$MYREQUEST['COUNT'];
7029 +// authentication needed?
7031 +if (!USE_AUTHENTICATION) {
7035 + if (ADMIN_PASSWORD!='password' && ($MYREQUEST['LO'] == 1 || isset($_SERVER['PHP_AUTH_USER']))) {
7037 + if (!isset($_SERVER['PHP_AUTH_USER']) ||
7038 + !isset($_SERVER['PHP_AUTH_PW']) ||
7039 + $_SERVER['PHP_AUTH_USER'] != ADMIN_USERNAME ||
7040 + $_SERVER['PHP_AUTH_PW'] != ADMIN_PASSWORD) {
7041 + Header("WWW-Authenticate: Basic realm=\"APC Login\"");
7042 + Header("HTTP/1.0 401 Unauthorized");
7046 + <h1>Rejected!</h1>
7047 + <big>Wrong Username or Password!</big><br/> <br/>
7048 + <big><a href='$PHP_SELF?OB={$MYREQUEST['OB']}'>Continue...</a></big>
7059 +// select cache mode
7060 +if ($AUTHENTICATED && $MYREQUEST['OB'] == OB_USER_CACHE) {
7061 + $cache_mode='user';
7064 +if ($AUTHENTICATED && isset($MYREQUEST['CC']) && $MYREQUEST['CC']) {
7065 + apc_clear_cache($cache_mode);
7068 +if(!function_exists('apc_cache_info') || !($cache=@apc_cache_info($cache_mode))) {
7069 + echo "No cache info available. APC does not appear to be running.";
7073 +$cache_user = apc_cache_info('user', 1);
7074 +$mem=apc_sma_info();
7075 +if(!$cache['num_hits']) { $cache['num_hits']=1; $time++; } // Avoid division by 0 errors on a cache clear
7077 +// don't cache this page
7079 +header("Cache-Control: no-store, no-cache, must-revalidate"); // HTTP/1.1
7080 +header("Cache-Control: post-check=0, pre-check=0", false);
7081 +header("Pragma: no-cache"); // HTTP/1.0
7083 +function duration($ts) {
7085 + $years = (int)((($time - $ts)/(7*86400))/52.177457);
7086 + $rem = (int)(($time-$ts)-($years * 52.177457 * 7 * 86400));
7087 + $weeks = (int)(($rem)/(7*86400));
7088 + $days = (int)(($rem)/86400) - $weeks*7;
7089 + $hours = (int)(($rem)/3600) - $days*24 - $weeks*7*24;
7090 + $mins = (int)(($rem)/60) - $hours*60 - $days*24*60 - $weeks*7*24*60;
7092 + if($years==1) $str .= "$years year, ";
7093 + if($years>1) $str .= "$years years, ";
7094 + if($weeks==1) $str .= "$weeks week, ";
7095 + if($weeks>1) $str .= "$weeks weeks, ";
7096 + if($days==1) $str .= "$days day,";
7097 + if($days>1) $str .= "$days days,";
7098 + if($hours == 1) $str .= " $hours hour and";
7099 + if($hours>1) $str .= " $hours hours and";
7100 + if($mins == 1) $str .= " 1 minute";
7101 + else $str .= " $mins minutes";
7107 +function graphics_avail() {
7108 + return extension_loaded('gd');
7110 +if (isset($MYREQUEST['IMG']))
7112 + if (!graphics_avail()) {
7116 + function fill_arc($im, $centerX, $centerY, $diameter, $start, $end, $color1,$color2,$text='',$placeindex=0) {
7118 + $w=deg2rad((360+$start+($end-$start)/2)%360);
7121 + if (function_exists("imagefilledarc")) {
7122 + // exists only if GD 2.0.1 is avaliable
7123 + imagefilledarc($im, $centerX+1, $centerY+1, $diameter, $diameter, $start, $end, $color1, IMG_ARC_PIE);
7124 + imagefilledarc($im, $centerX, $centerY, $diameter, $diameter, $start, $end, $color2, IMG_ARC_PIE);
7125 + imagefilledarc($im, $centerX, $centerY, $diameter, $diameter, $start, $end, $color1, IMG_ARC_NOFILL|IMG_ARC_EDGED);
7127 + imagearc($im, $centerX, $centerY, $diameter, $diameter, $start, $end, $color2);
7128 + imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($start)) * $r, $centerY + sin(deg2rad($start)) * $r, $color2);
7129 + imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($start+1)) * $r, $centerY + sin(deg2rad($start)) * $r, $color2);
7130 + imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($end-1)) * $r, $centerY + sin(deg2rad($end)) * $r, $color2);
7131 + imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($end)) * $r, $centerY + sin(deg2rad($end)) * $r, $color2);
7132 + imagefill($im,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2, $color2);
7135 + if ($placeindex>0) {
7136 + imageline($im,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$diameter, $placeindex*12,$color1);
7137 + imagestring($im,4,$diameter, $placeindex*12,$text,$color1);
7140 + imagestring($im,4,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$text,$color1);
7145 + function text_arc($im, $centerX, $centerY, $diameter, $start, $end, $color1,$text,$placeindex=0) {
7147 + $w=deg2rad((360+$start+($end-$start)/2)%360);
7149 + if ($placeindex>0) {
7150 + imageline($im,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$diameter, $placeindex*12,$color1);
7151 + imagestring($im,4,$diameter, $placeindex*12,$text,$color1);
7154 + imagestring($im,4,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$text,$color1);
7158 + function fill_box($im, $x, $y, $w, $h, $color1, $color2,$text='',$placeindex='') {
7159 + global $col_black;
7163 + imagerectangle($im, $x, $y1, $x1+1, $y+1, $col_black);
7164 + if($y1>$y) imagefilledrectangle($im, $x, $y, $x1, $y1, $color2);
7165 + else imagefilledrectangle($im, $x, $y1, $x1, $y, $color2);
7166 + imagerectangle($im, $x, $y1, $x1, $y, $color1);
7168 + if ($placeindex>0) {
7170 + if ($placeindex<16)
7173 + $py=$placeindex*12+6;
7174 + imagefilledrectangle($im, $px+90, $py+3, $px+90-4, $py-3, $color2);
7175 + imageline($im,$x,$y+$h/2,$px+90,$py,$color2);
7176 + imagestring($im,2,$px,$py-6,$text,$color1);
7179 + if ($placeindex<31) {
7181 + $py=($placeindex-15)*12+6;
7183 + $px=$x+40*2+100*intval(($placeindex-15)/15);
7184 + $py=($placeindex%15)*12+6;
7186 + imagefilledrectangle($im, $px, $py+3, $px-4, $py-3, $color2);
7187 + imageline($im,$x+$w,$y+$h/2,$px,$py,$color2);
7188 + imagestring($im,2,$px+2,$py-6,$text,$color1);
7191 + imagestring($im,4,$x+5,$y1-16,$text,$color1);
7197 + $size = GRAPH_SIZE; // image size
7198 + if ($MYREQUEST['IMG']==3)
7199 + $image = imagecreate(2*$size+150, $size+10);
7201 + $image = imagecreate($size+50, $size+10);
7203 + $col_white = imagecolorallocate($image, 0xFF, 0xFF, 0xFF);
7204 + $col_red = imagecolorallocate($image, 0xD0, 0x60, 0x30);
7205 + $col_green = imagecolorallocate($image, 0x60, 0xF0, 0x60);
7206 + $col_black = imagecolorallocate($image, 0, 0, 0);
7207 + imagecolortransparent($image,$col_white);
7209 + switch ($MYREQUEST['IMG']) {
7212 + $s=$mem['num_seg']*$mem['seg_size'];
7213 + $a=$mem['avail_mem'];
7217 + // This block of code creates the pie chart. It is a lot more complex than you
7218 + // would expect because we try to visualize any memory fragmentation as well.
7220 + $string_placement=array();
7221 + for($i=0; $i<$mem['num_seg']; $i++) {
7223 + $free = $mem['block_lists'][$i];
7224 + foreach($free as $block) {
7225 + if($block['offset']!=$ptr) { // Used block
7226 + $angle_to = $angle_from+($block['offset']-$ptr)/$s;
7227 + if(($angle_to+$fuzz)>1) $angle_to = 1;
7228 + fill_arc($image,$x,$y,$size,$angle_from*360,$angle_to*360,$col_black,$col_red);
7229 + if (($angle_to-$angle_from)>0.05) {
7230 + array_push($string_placement, array($angle_from,$angle_to));
7232 + $angle_from = $angle_to;
7234 + $angle_to = $angle_from+($block['size'])/$s;
7235 + if(($angle_to+$fuzz)>1) $angle_to = 1;
7236 + fill_arc($image,$x,$y,$size,$angle_from*360,$angle_to*360,$col_black,$col_green);
7237 + if (($angle_to-$angle_from)>0.05) {
7238 + array_push($string_placement, array($angle_from,$angle_to));
7240 + $angle_from = $angle_to;
7241 + $ptr = $block['offset']+$block['size'];
7243 + if ($ptr < $mem['seg_size']) { // memory at the end
7244 + $angle_to = $angle_from + ($mem['seg_size'] - $ptr)/$s;
7245 + if(($angle_to+$fuzz)>1) $angle_to = 1;
7246 + fill_arc($image,$x,$y,$size,$angle_from*360,$angle_to*360,$col_black,$col_red);
7247 + if (($angle_to-$angle_from)>0.05) {
7248 + array_push($string_placement, array($angle_from,$angle_to));
7252 + foreach ($string_placement as $angle) {
7253 + text_arc($image,$x,$y,$size,$angle[0]*360,$angle[1]*360,$col_black,bsize($s*($angle[1]-$angle[0])));
7258 + $s=$cache['num_hits']+$cache['num_misses'];
7259 + $a=$cache['num_hits'];
7261 + fill_box($image, 30,$size,50,-$a*($size-21)/$s,$col_black,$col_green,sprintf("%.1f%%",$cache['num_hits']*100/$s));
7262 + fill_box($image,130,$size,50,-max(4,($s-$a)*($size-21)/$s),$col_black,$col_red,sprintf("%.1f%%",$cache['num_misses']*100/$s));
7266 + $s=$mem['num_seg']*$mem['seg_size'];
7267 + $a=$mem['avail_mem'];
7272 + // This block of code creates the bar chart. It is a lot more complex than you
7273 + // would expect because we try to visualize any memory fragmentation as well.
7274 + for($i=0; $i<$mem['num_seg']; $i++) {
7276 + $free = $mem['block_lists'][$i];
7277 + foreach($free as $block) {
7278 + if($block['offset']!=$ptr) { // Used block
7279 + $h=(GRAPH_SIZE-5)*($block['offset']-$ptr)/$s;
7282 + if($j<75) fill_box($image,$x,$y,50,$h,$col_black,$col_red,bsize($block['offset']-$ptr),$j);
7283 + else fill_box($image,$x,$y,50,$h,$col_black,$col_red);
7287 + $h=(GRAPH_SIZE-5)*($block['size'])/$s;
7290 + if($j<75) fill_box($image,$x,$y,50,$h,$col_black,$col_green,bsize($block['size']),$j);
7291 + else fill_box($image,$x,$y,50,$h,$col_black,$col_green);
7294 + $ptr = $block['offset']+$block['size'];
7296 + if ($ptr < $mem['seg_size']) { // memory at the end
7297 + $h = (GRAPH_SIZE-5) * ($mem['seg_size'] - $ptr) / $s;
7299 + fill_box($image,$x,$y,50,$h,$col_black,$col_red,bsize($mem['seg_size']-$ptr),$j++);
7305 + $s=$cache['num_hits']+$cache['num_misses'];
7306 + $a=$cache['num_hits'];
7308 + fill_box($image, 30,$size,50,-$a*($size-21)/$s,$col_black,$col_green,sprintf("%.1f%%",$cache['num_hits']*100/$s));
7309 + fill_box($image,130,$size,50,-max(4,($s-$a)*($size-21)/$s),$col_black,$col_red,sprintf("%.1f%%",$cache['num_misses']*100/$s));
7313 + header("Content-type: image/png");
7318 +// pretty printer for byte values
7320 +function bsize($s) {
7321 + foreach (array('','K','M','G') as $i => $k) {
7322 + if ($s < 1024) break;
7325 + return sprintf("%5.1f %sBytes",$s,$k);
7328 +// sortable table header in "scripts for this host" view
7329 +function sortheader($key,$name,$extra='') {
7330 + global $MYREQUEST, $MY_SELF_WO_SORT;
7332 + if ($MYREQUEST['SORT1']==$key) {
7333 + $MYREQUEST['SORT2'] = $MYREQUEST['SORT2']=='A' ? 'D' : 'A';
7335 + return "<a class=sortable href=\"$MY_SELF_WO_SORT$extra&SORT1=$key&SORT2=".$MYREQUEST['SORT2']."\">$name</a>";
7339 +// create menu entry
7340 +function menu_entry($ob,$title) {
7341 + global $MYREQUEST,$MY_SELF;
7342 + if ($MYREQUEST['OB']!=$ob) {
7343 + return "<li><a href=\"$MY_SELF&OB=$ob\">$title</a></li>";
7344 + } else if (empty($MYREQUEST['SH'])) {
7345 + return "<li><span class=active>$title</span></li>";
7347 + return "<li><a class=\"child_active\" href=\"$MY_SELF&OB=$ob\">$title</a></li>";
7351 +function put_login_link($s="Login")
7353 + global $MY_SELF,$MYREQUEST,$AUTHENTICATED;
7354 + // needs ADMIN_PASSWORD to be changed!
7356 + if (!USE_AUTHENTICATION) {
7358 + } else if (ADMIN_PASSWORD=='password')
7361 + <a href="#" onClick="javascript:alert('You need to set a password at the top of apc.php before this will work!');return false";>$s</a>
7363 + } else if ($AUTHENTICATED) {
7365 + '{$_SERVER['PHP_AUTH_USER']}' logged in!
7369 + <a href="$MY_SELF&LO=1&OB={$MYREQUEST['OB']}">$s</a>
7376 +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
7378 +<head><title>APC INFO <?php echo $host ?></title>
7380 +body { background:white; font-size:100.01%; margin:0; padding:0; }
7381 +body,p,td,th,input,submit { font-size:0.8em;font-family:arial,helvetica,sans-serif; }
7382 +* html body {font-size:0.8em}
7383 +* html p {font-size:0.8em}
7384 +* html td {font-size:0.8em}
7385 +* html th {font-size:0.8em}
7386 +* html input {font-size:0.8em}
7387 +* html submit {font-size:0.8em}
7388 +td { vertical-align:top }
7389 +a { color:black; font-weight:none; text-decoration:none; }
7390 +a:hover { text-decoration:underline; }
7391 +div.content { padding:1em 1em 1em 1em; position:absolute; width:97%; z-index:100; }
7394 +div.head div.login {
7395 + position:absolute;
7401 +div.head div.login a {
7402 + position:absolute;
7404 + background:rgb(119,123,180);
7405 + border:solid rgb(102,102,153) 2px;
7408 + padding:0.1em 0.5em 0.1em 0.5em;
7409 + text-decoration:none;
7411 +div.head div.login a:hover {
7412 + background:rgb(193,193,244);
7415 +h1.apc { background:rgb(153,153,204); margin:0; padding:0.5em 1em 0.5em 1em; }
7416 +* html h1.apc { margin-bottom:-7px; }
7417 +h1.apc a:hover { text-decoration:none; color:rgb(90,90,90); }
7418 +h1.apc div.logo span.logo {
7419 + background:rgb(119,123,180);
7421 + border-right: solid black 1px;
7422 + border-bottom: solid black 1px;
7423 + font-style:italic;
7425 + padding-left:1.2em;
7426 + padding-right:1.2em;
7429 +h1.apc div.logo span.name { color:white; font-size:0.7em; padding:0 0.8em 0 2em; }
7430 +h1.apc div.nameinfo { color:white; display:inline; font-size:0.4em; margin-left: 3em; }
7431 +h1.apc div.copy { color:black; font-size:0.4em; position:absolute; right:1em; }
7434 + border-bottom:solid rgb(102,102,153) 1px;
7435 + border-style:none;
7436 + border-top:solid rgb(102,102,153) 10px;
7443 +ol,menu { margin:1em 0 0 0; padding:0.2em; margin-left:1em;}
7444 +ol.menu li { display:inline; margin-right:0.7em; list-style:none; font-size:85%}
7446 + background:rgb(153,153,204);
7447 + border:solid rgb(102,102,153) 2px;
7451 + padding:0.1em 0.5em 0.1em 0.5em;
7452 + text-decoration:none;
7455 +ol.menu a.child_active {
7456 + background:rgb(153,153,204);
7457 + border:solid rgb(102,102,153) 2px;
7461 + padding:0.1em 0.5em 0.1em 0.5em;
7462 + text-decoration:none;
7463 + border-left: solid black 5px;
7466 +ol.menu span.active {
7467 + background:rgb(153,153,204);
7468 + border:solid rgb(102,102,153) 2px;
7472 + padding:0.1em 0.5em 0.1em 0.5em;
7473 + text-decoration:none;
7474 + border-left: solid black 5px;
7476 +ol.menu span.inactive {
7477 + background:rgb(193,193,244);
7478 + border:solid rgb(182,182,233) 2px;
7482 + padding:0.1em 0.5em 0.1em 0.5em;
7483 + text-decoration:none;
7487 + background:rgb(193,193,244);
7488 + text-decoration:none;
7493 + background:rgb(204,204,204);
7494 + border:solid rgb(204,204,204) 1px;
7495 + margin-bottom:1em;
7498 + background:rgb(204,204,204);
7502 + padding:0.1em 1em 0.1em 1em;
7505 + border:solid rgb(204,204,204) 1px;
7509 +div.info table th {
7510 + background:rgb(204,204,204);
7513 + padding:0.1em 1em 0.1em 1em;
7515 +div.info table th a.sortable { color:black; }
7516 +div.info table tr.tr-0 { background:rgb(238,238,238); }
7517 +div.info table tr.tr-1 { background:rgb(221,221,221); }
7518 +div.info table td { padding:0.3em 1em 0.3em 1em; }
7519 +div.info table td.td-0 { border-right:solid rgb(102,102,153) 1px; white-space:nowrap; }
7520 +div.info table td.td-n { border-right:solid rgb(102,102,153) 1px; }
7521 +div.info table td h3 {
7524 + margin-left:-0.3em;
7527 +div.graph { margin-bottom:1em }
7528 +div.graph h2 { background:rgb(204,204,204);; color:black; font-size:1em; margin:0; padding:0.1em 1em 0.1em 1em; }
7529 +div.graph table { border:solid rgb(204,204,204) 1px; color:black; font-weight:normal; width:100%; }
7530 +div.graph table td.td-0 { background:rgb(238,238,238); }
7531 +div.graph table td.td-1 { background:rgb(221,221,221); }
7532 +div.graph table td { padding:0.2em 1em 0.4em 1em; }
7534 +div.div1,div.div2 { margin-bottom:1em; width:35em; }
7535 +div.div3 { position:absolute; left:40em; top:1em; width:580px; }
7536 +//div.div3 { position:absolute; left:37em; top:1em; right:1em; }
7538 +div.sorting { margin:1.5em 0em 1.5em 2em }
7539 +.center { text-align:center }
7540 +.aright { position:absolute;right:1em }
7541 +.right { text-align:right }
7542 +.ok { color:rgb(0,200,0); font-weight:bold}
7543 +.failed { color:rgb(200,0,0); font-weight:bold}
7546 + border: black solid 1px;
7547 + border-right:solid black 2px;
7548 + border-bottom:solid black 2px;
7549 + padding:0 0.5em 0 0.5em;
7552 +span.green { background:#60F060; padding:0 0.5em 0 0.5em}
7553 +span.red { background:#D06030; padding:0 0.5em 0 0.5em }
7556 + background:rgb(238,238,238);
7557 + border:solid rgb(204,204,204) 1px;
7558 + color:rgb(200,0,0);
7562 + text-align:center;
7566 + background:rgb(153,153,204);
7567 + border:solid rgb(102,102,153) 2px;
7571 + padding:0.1em 0.5em 0.1em 0.5em;
7579 + <div class="logo"><span class="logo"><a href="http://pecl.php.net/package/APC">APC</a></span></div>
7580 + <div class="nameinfo">Opcode Cache</div>
7582 + <div class="login">
7583 + <?php put_login_link(); ?>
7590 +// Display main Menu
7593 + <li><a href="$MY_SELF&OB={$MYREQUEST['OB']}&SH={$MYREQUEST['SH']}">Refresh Data</a></li>
7596 + menu_entry(1,'View Host Stats'),
7597 + menu_entry(2,'System Cache Entries');
7598 +if ($AUTHENTICATED) {
7599 + echo menu_entry(4,'Per-Directory Entries');
7602 + menu_entry(3,'User Cache Entries'),
7603 + menu_entry(9,'Version Check');
7605 +if ($AUTHENTICATED) {
7607 + <li><a class="aright" href="$MY_SELF&CC=1&OB={$MYREQUEST['OB']}" onClick="javascipt:return confirm('Are you sure?');">Clear $cache_mode Cache</a></li>
7617 + <div class=content>
7620 +// MAIN SWITCH STATEMENT
7622 +switch ($MYREQUEST['OB']) {
7628 +// -----------------------------------------------
7630 +// -----------------------------------------------
7631 +case OB_HOST_STATS:
7632 + $mem_size = $mem['num_seg']*$mem['seg_size'];
7633 + $mem_avail= $mem['avail_mem'];
7634 + $mem_used = $mem_size-$mem_avail;
7635 + $seg_size = bsize($mem['seg_size']);
7636 + $req_rate = sprintf("%.2f",($cache['num_hits']+$cache['num_misses'])/($time-$cache['start_time']));
7637 + $hit_rate = sprintf("%.2f",($cache['num_hits'])/($time-$cache['start_time']));
7638 + $miss_rate = sprintf("%.2f",($cache['num_misses'])/($time-$cache['start_time']));
7639 + $insert_rate = sprintf("%.2f",($cache['num_inserts'])/($time-$cache['start_time']));
7640 + $req_rate_user = sprintf("%.2f",($cache_user['num_hits']+$cache_user['num_misses'])/($time-$cache_user['start_time']));
7641 + $hit_rate_user = sprintf("%.2f",($cache_user['num_hits'])/($time-$cache_user['start_time']));
7642 + $miss_rate_user = sprintf("%.2f",($cache_user['num_misses'])/($time-$cache_user['start_time']));
7643 + $insert_rate_user = sprintf("%.2f",($cache_user['num_inserts'])/($time-$cache_user['start_time']));
7644 + $apcversion = phpversion('apc');
7645 + $phpversion = phpversion();
7646 + $number_files = $cache['num_entries'];
7647 + $size_files = bsize($cache['mem_size']);
7648 + $number_vars = $cache_user['num_entries'];
7649 + $size_vars = bsize($cache_user['mem_size']);
7652 + <div class="info div1"><h2>General Cache Information</h2>
7653 + <table cellspacing=0><tbody>
7654 + <tr class=tr-0><td class=td-0>APC Version</td><td>$apcversion</td></tr>
7655 + <tr class=tr-1><td class=td-0>PHP Version</td><td>$phpversion</td></tr>
7658 + if(!empty($_SERVER['SERVER_NAME']))
7659 + echo "<tr class=tr-0><td class=td-0>APC Host</td><td>{$_SERVER['SERVER_NAME']} $host</td></tr>\n";
7660 + if(!empty($_SERVER['SERVER_SOFTWARE']))
7661 + echo "<tr class=tr-1><td class=td-0>Server Software</td><td>{$_SERVER['SERVER_SOFTWARE']}</td></tr>\n";
7664 + <tr class=tr-0><td class=td-0>Shared Memory</td><td>{$mem['num_seg']} Segment(s) with $seg_size
7665 + <br/> ({$cache['memory_type']} memory, {$cache['locking_type']} locking)
7668 + echo '<tr class=tr-1><td class=td-0>Start Time</td><td>',date(DATE_FORMAT,$cache['start_time']),'</td></tr>';
7669 + echo '<tr class=tr-0><td class=td-0>Uptime</td><td>',duration($cache['start_time']),'</td></tr>';
7670 + echo '<tr class=tr-1><td class=td-0>File Upload Support</td><td>',$cache['file_upload_progress'],'</td></tr>';
7675 + <div class="info div1"><h2>File Cache Information</h2>
7676 + <table cellspacing=0><tbody>
7677 + <tr class=tr-0><td class=td-0>Cached Files</td><td>$number_files ($size_files)</td></tr>
7678 + <tr class=tr-1><td class=td-0>Hits</td><td>{$cache['num_hits']}</td></tr>
7679 + <tr class=tr-0><td class=td-0>Misses</td><td>{$cache['num_misses']}</td></tr>
7680 + <tr class=tr-1><td class=td-0>Request Rate (hits, misses)</td><td>$req_rate cache requests/second</td></tr>
7681 + <tr class=tr-0><td class=td-0>Hit Rate</td><td>$hit_rate cache requests/second</td></tr>
7682 + <tr class=tr-1><td class=td-0>Miss Rate</td><td>$miss_rate cache requests/second</td></tr>
7683 + <tr class=tr-0><td class=td-0>Insert Rate</td><td>$insert_rate cache requests/second</td></tr>
7684 + <tr class=tr-1><td class=td-0>Cache full count</td><td>{$cache['expunges']}</td></tr>
7688 + <div class="info div1"><h2>User Cache Information</h2>
7689 + <table cellspacing=0><tbody>
7690 + <tr class=tr-0><td class=td-0>Cached Variables</td><td>$number_vars ($size_vars)</td></tr>
7691 + <tr class=tr-1><td class=td-0>Hits</td><td>{$cache_user['num_hits']}</td></tr>
7692 + <tr class=tr-0><td class=td-0>Misses</td><td>{$cache_user['num_misses']}</td></tr>
7693 + <tr class=tr-1><td class=td-0>Request Rate (hits, misses)</td><td>$req_rate_user cache requests/second</td></tr>
7694 + <tr class=tr-0><td class=td-0>Hit Rate</td><td>$hit_rate_user cache requests/second</td></tr>
7695 + <tr class=tr-1><td class=td-0>Miss Rate</td><td>$miss_rate_user cache requests/second</td></tr>
7696 + <tr class=tr-0><td class=td-0>Insert Rate</td><td>$insert_rate_user cache requests/second</td></tr>
7697 + <tr class=tr-1><td class=td-0>Cache full count</td><td>{$cache_user['expunges']}</td></tr>
7702 + <div class="info div2"><h2>Runtime Settings</h2><table cellspacing=0><tbody>
7706 + foreach (ini_get_all('apc') as $k => $v) {
7707 + echo "<tr class=tr-$j><td class=td-0>",$k,"</td><td>",str_replace(',',',<br />',$v['local_value']),"</td></tr>\n";
7711 + if($mem['num_seg']>1 || $mem['num_seg']==1 && count($mem['block_lists'][0])>1)
7712 + $mem_note = "Memory Usage<br /><font size=-2>(multiple slices indicate fragments)</font>";
7714 + $mem_note = "Memory Usage";
7720 + <div class="graph div3"><h2>Host Status Diagrams</h2>
7721 + <table cellspacing=0><tbody>
7723 + $size='width='.(GRAPH_SIZE+50).' height='.(GRAPH_SIZE+10);
7726 + <td class=td-0>$mem_note</td>
7727 + <td class=td-1>Hits & Misses</td>
7732 + graphics_avail() ?
7734 + "<td class=td-0><img alt=\"\" $size src=\"$PHP_SELF?IMG=1&$time\"></td>".
7735 + "<td class=td-1><img alt=\"\" $size src=\"$PHP_SELF?IMG=2&$time\"></td></tr>\n"
7738 + '<td class=td-0><span class="green box"> </span>Free: ',bsize($mem_avail).sprintf(" (%.1f%%)",$mem_avail*100/$mem_size),"</td>\n",
7739 + '<td class=td-1><span class="green box"> </span>Hits: ',$cache['num_hits'].sprintf(" (%.1f%%)",$cache['num_hits']*100/($cache['num_hits']+$cache['num_misses'])),"</td>\n",
7742 + '<td class=td-0><span class="red box"> </span>Used: ',bsize($mem_used ).sprintf(" (%.1f%%)",$mem_used *100/$mem_size),"</td>\n",
7743 + '<td class=td-1><span class="red box"> </span>Misses: ',$cache['num_misses'].sprintf(" (%.1f%%)",$cache['num_misses']*100/($cache['num_hits']+$cache['num_misses'])),"</td>\n";
7749 + <h2>Detailed Memory Usage and Fragmentation</h2>
7750 + <table cellspacing=0><tbody>
7752 + <td class=td-0 colspan=2><br/>
7755 + // Fragementation: (freeseg - 1) / total_seg
7756 + $nseg = $freeseg = $fragsize = $freetotal = 0;
7757 + for($i=0; $i<$mem['num_seg']; $i++) {
7759 + foreach($mem['block_lists'][$i] as $block) {
7760 + if ($block['offset'] != $ptr) {
7763 + $ptr = $block['offset'] + $block['size'];
7764 + /* Only consider blocks <5M for the fragmentation % */
7765 + if($block['size']<(5*1024*1024)) $fragsize+=$block['size'];
7766 + $freetotal+=$block['size'];
7768 + $freeseg += count($mem['block_lists'][$i]);
7771 + if ($freeseg > 1) {
7772 + $frag = sprintf("%.2f%% (%s out of %s in %d fragments)", ($fragsize/$freetotal)*100,bsize($fragsize),bsize($freetotal),$freeseg);
7777 + if (graphics_avail()) {
7778 + $size='width='.(2*GRAPH_SIZE+150).' height='.(GRAPH_SIZE+10);
7780 + <img alt="" $size src="$PHP_SELF?IMG=3&$time">
7784 + </br>Fragmentation: $frag
7788 + if(isset($mem['adist'])) {
7789 + foreach($mem['adist'] as $i=>$v) {
7790 + $cur = pow(2,$i); $nxt = pow(2,$i+1)-1;
7791 + if($i==0) $range = "1";
7792 + else $range = "$cur - $nxt";
7793 + echo "<tr><th align=right>$range</th><td align=right>$v</td></tr>\n";
7804 +// -----------------------------------------------
7805 +// User Cache Entries
7806 +// -----------------------------------------------
7807 +case OB_USER_CACHE:
7808 + if (!$AUTHENTICATED) {
7809 + echo '<div class="authneeded">You need to login to see the user values here!<br/> <br/>';
7810 + put_login_link("Login now!");
7814 + $fieldname='info';
7815 + $fieldheading='User Entry Label';
7819 +// -----------------------------------------------
7820 +// System Cache Entries
7821 +// -----------------------------------------------
7823 + if (!isset($fieldname))
7825 + $fieldname='filename';
7826 + $fieldheading='Script Filename';
7827 + if(ini_get("apc.stat")) $fieldkey='inode';
7828 + else $fieldkey='filename';
7830 + if (!empty($MYREQUEST['SH']))
7833 + <div class="info"><table cellspacing=0><tbody>
7834 + <tr><th>Attribute</th><th>Value</th></tr>
7838 + foreach($scope_list as $j => $list) {
7839 + foreach($cache[$list] as $i => $entry) {
7840 + if (md5($entry[$fieldkey])!=$MYREQUEST['SH']) continue;
7841 + foreach($entry as $k => $value) {
7842 + if (!$AUTHENTICATED) {
7843 + // hide all path entries if not logged in
7844 + $value=preg_replace('/^.*(\\/|\\\\)/','<i><hidden></i>/',$value);
7847 + if ($k == "num_hits") {
7848 + $value=sprintf("%s (%.2f%%)",$value,$value*100/$cache['num_hits']);
7850 + if ($k == 'deletion_time') {
7851 + if(!$entry['deletion_time']) $value = "None";
7854 + "<tr class=tr-$m>",
7855 + "<td class=td-0>",ucwords(preg_replace("/_/"," ",$k)),"</td>",
7856 + "<td class=td-last>",(preg_match("/time/",$k) && $value!='None') ? date(DATE_FORMAT,$value) : $value,"</td>",
7860 + if($fieldkey=='info') {
7861 + echo "<tr class=tr-$m><td class=td-0>Stored Value</td><td class=td-last><pre>";
7862 + $output = var_export(apc_fetch($entry[$fieldkey]),true);
7863 + echo htmlspecialchars($output);
7864 + echo "</pre></td></tr>\n";
7879 + <div class=sorting><form>Scope:
7880 + <input type=hidden name=OB value={$MYREQUEST['OB']}>
7881 + <select name=SCOPE>
7884 + "<option value=A",$MYREQUEST['SCOPE']=='A' ? " selected":"",">Active</option>",
7885 + "<option value=D",$MYREQUEST['SCOPE']=='D' ? " selected":"",">Deleted</option>",
7887 + ", Sorting:<select name=SORT1>",
7888 + "<option value=H",$MYREQUEST['SORT1']=='H' ? " selected":"",">Hits</option>",
7889 + "<option value=Z",$MYREQUEST['SORT1']=='Z' ? " selected":"",">Size</option>",
7890 + "<option value=S",$MYREQUEST['SORT1']=='S' ? " selected":"",">$fieldheading</option>",
7891 + "<option value=A",$MYREQUEST['SORT1']=='A' ? " selected":"",">Last accessed</option>",
7892 + "<option value=M",$MYREQUEST['SORT1']=='M' ? " selected":"",">Last modified</option>",
7893 + "<option value=C",$MYREQUEST['SORT1']=='C' ? " selected":"",">Created at</option>",
7894 + "<option value=D",$MYREQUEST['SORT1']=='D' ? " selected":"",">Deleted at</option>";
7895 + if($fieldname=='info') echo
7896 + "<option value=D",$MYREQUEST['SORT1']=='T' ? " selected":"",">Timeout</option>";
7899 + '<select name=SORT2>',
7900 + '<option value=D',$MYREQUEST['SORT2']=='D' ? ' selected':'','>DESC</option>',
7901 + '<option value=A',$MYREQUEST['SORT2']=='A' ? ' selected':'','>ASC</option>',
7903 + '<select name=COUNT onChange="form.submit()">',
7904 + '<option value=10 ',$MYREQUEST['COUNT']=='10' ? ' selected':'','>Top 10</option>',
7905 + '<option value=20 ',$MYREQUEST['COUNT']=='20' ? ' selected':'','>Top 20</option>',
7906 + '<option value=50 ',$MYREQUEST['COUNT']=='50' ? ' selected':'','>Top 50</option>',
7907 + '<option value=100',$MYREQUEST['COUNT']=='100'? ' selected':'','>Top 100</option>',
7908 + '<option value=150',$MYREQUEST['COUNT']=='150'? ' selected':'','>Top 150</option>',
7909 + '<option value=200',$MYREQUEST['COUNT']=='200'? ' selected':'','>Top 200</option>',
7910 + '<option value=500',$MYREQUEST['COUNT']=='500'? ' selected':'','>Top 500</option>',
7911 + '<option value=0 ',$MYREQUEST['COUNT']=='0' ? ' selected':'','>All</option>',
7913 + ' Search: <input name=SEARCH value="',$MYREQUEST['SEARCH'],'" type=text size=25/>',
7914 + ' <input type=submit value="GO!">',
7917 + '<div class="info"><table cellspacing=0><tbody>',
7919 + '<th>',sortheader('S',$fieldheading, "&OB=".$MYREQUEST['OB']),'</th>',
7920 + '<th>',sortheader('H','Hits', "&OB=".$MYREQUEST['OB']),'</th>',
7921 + '<th>',sortheader('Z','Size', "&OB=".$MYREQUEST['OB']),'</th>',
7922 + '<th>',sortheader('A','Last accessed',"&OB=".$MYREQUEST['OB']),'</th>',
7923 + '<th>',sortheader('M','Last modified',"&OB=".$MYREQUEST['OB']),'</th>',
7924 + '<th>',sortheader('C','Created at', "&OB=".$MYREQUEST['OB']),'</th>';
7926 + if($fieldname=='info') {
7928 + echo '<th>',sortheader('T','Timeout',"&OB=".$MYREQUEST['OB']),'</th>';
7930 + echo '<th>',sortheader('D','Deleted at',"&OB=".$MYREQUEST['OB']),'</th></tr>';
7932 + // builds list with alpha numeric sortable keys
7935 + foreach($cache[$scope_list[$MYREQUEST['SCOPE']]] as $i => $entry) {
7936 + switch($MYREQUEST['SORT1']) {
7937 + case 'A': $k=sprintf('%015d-',$entry['access_time']); break;
7938 + case 'H': $k=sprintf('%015d-',$entry['num_hits']); break;
7939 + case 'Z': $k=sprintf('%015d-',$entry['mem_size']); break;
7940 + case 'M': $k=sprintf('%015d-',$entry['mtime']); break;
7941 + case 'C': $k=sprintf('%015d-',$entry['creation_time']); break;
7942 + case 'T': $k=sprintf('%015d-',$entry['ttl']); break;
7943 + case 'D': $k=sprintf('%015d-',$entry['deletion_time']); break;
7944 + case 'S': $k=''; break;
7946 + if (!$AUTHENTICATED) {
7947 + // hide all path entries if not logged in
7948 + $list[$k.$entry[$fieldname]]=preg_replace('/^.*(\\/|\\\\)/','<i><hidden></i>/',$entry);
7950 + $list[$k.$entry[$fieldname]]=$entry;
7958 + switch ($MYREQUEST['SORT2']) {
7959 + case "A": krsort($list); break;
7960 + case "D": ksort($list); break;
7965 + foreach($list as $k => $entry) {
7966 + if(!$MYREQUEST['SEARCH'] || preg_match('/'.$MYREQUEST['SEARCH'].'/i', $entry[$fieldname]) != 0) {
7968 + '<tr class=tr-',$i%2,'>',
7969 + "<td class=td-0><a href=\"$MY_SELF&OB=",$MYREQUEST['OB'],"&SH=",md5($entry[$fieldkey]),"\">",$entry[$fieldname],'</a></td>',
7970 + '<td class="td-n center">',$entry['num_hits'],'</td>',
7971 + '<td class="td-n right">',$entry['mem_size'],'</td>',
7972 + '<td class="td-n center">',date(DATE_FORMAT,$entry['access_time']),'</td>',
7973 + '<td class="td-n center">',date(DATE_FORMAT,$entry['mtime']),'</td>',
7974 + '<td class="td-n center">',date(DATE_FORMAT,$entry['creation_time']),'</td>';
7976 + if($fieldname=='info') {
7978 + echo '<td class="td-n center">'.$entry['ttl'].' seconds</td>';
7980 + echo '<td class="td-n center">None</td>';
7983 + '<td class="td-last center">',$entry['deletion_time'] ? date(DATE_FORMAT,$entry['deletion_time']) : '-','</td>',
7986 + if ($i == $MYREQUEST['COUNT'])
7992 + echo '<tr class=tr-0><td class="center" colspan=',$cols,'><i>No data</i></td></tr>';
7998 + if ($list && $i < count($list)) {
7999 + echo "<a href=\"$MY_SELF&OB=",$MYREQUEST['OB'],"&COUNT=0\"><i>",count($list)-$i,' more available...</i></a>';
8008 +// -----------------------------------------------
8009 +// Per-Directory System Cache Entries
8010 +// -----------------------------------------------
8011 +case OB_SYS_CACHE_DIR:
8012 + if (!$AUTHENTICATED) {
8017 + <div class=sorting><form>Scope:
8018 + <input type=hidden name=OB value={$MYREQUEST['OB']}>
8019 + <select name=SCOPE>
8022 + "<option value=A",$MYREQUEST['SCOPE']=='A' ? " selected":"",">Active</option>",
8023 + "<option value=D",$MYREQUEST['SCOPE']=='D' ? " selected":"",">Deleted</option>",
8025 + ", Sorting:<select name=SORT1>",
8026 + "<option value=H",$MYREQUEST['SORT1']=='H' ? " selected":"",">Total Hits</option>",
8027 + "<option value=Z",$MYREQUEST['SORT1']=='Z' ? " selected":"",">Total Size</option>",
8028 + "<option value=T",$MYREQUEST['SORT1']=='T' ? " selected":"",">Number of Files</option>",
8029 + "<option value=S",$MYREQUEST['SORT1']=='S' ? " selected":"",">Directory Name</option>",
8030 + "<option value=A",$MYREQUEST['SORT1']=='A' ? " selected":"",">Avg. Size</option>",
8031 + "<option value=C",$MYREQUEST['SORT1']=='C' ? " selected":"",">Avg. Hits</option>",
8033 + '<select name=SORT2>',
8034 + '<option value=D',$MYREQUEST['SORT2']=='D' ? ' selected':'','>DESC</option>',
8035 + '<option value=A',$MYREQUEST['SORT2']=='A' ? ' selected':'','>ASC</option>',
8037 + '<select name=COUNT onChange="form.submit()">',
8038 + '<option value=10 ',$MYREQUEST['COUNT']=='10' ? ' selected':'','>Top 10</option>',
8039 + '<option value=20 ',$MYREQUEST['COUNT']=='20' ? ' selected':'','>Top 20</option>',
8040 + '<option value=50 ',$MYREQUEST['COUNT']=='50' ? ' selected':'','>Top 50</option>',
8041 + '<option value=100',$MYREQUEST['COUNT']=='100'? ' selected':'','>Top 100</option>',
8042 + '<option value=150',$MYREQUEST['COUNT']=='150'? ' selected':'','>Top 150</option>',
8043 + '<option value=200',$MYREQUEST['COUNT']=='200'? ' selected':'','>Top 200</option>',
8044 + '<option value=500',$MYREQUEST['COUNT']=='500'? ' selected':'','>Top 500</option>',
8045 + '<option value=0 ',$MYREQUEST['COUNT']=='0' ? ' selected':'','>All</option>',
8047 + ", Group By Dir Level:<select name=AGGR>",
8048 + "<option value='' selected>None</option>";
8049 + for ($i = 1; $i < 10; $i++)
8050 + echo "<option value=$i",$MYREQUEST['AGGR']==$i ? " selected":"",">$i</option>";
8052 + ' <input type=submit value="GO!">',
8055 + '<div class="info"><table cellspacing=0><tbody>',
8057 + '<th>',sortheader('S','Directory Name', "&OB=".$MYREQUEST['OB']),'</th>',
8058 + '<th>',sortheader('T','Number of Files',"&OB=".$MYREQUEST['OB']),'</th>',
8059 + '<th>',sortheader('H','Total Hits', "&OB=".$MYREQUEST['OB']),'</th>',
8060 + '<th>',sortheader('Z','Total Size', "&OB=".$MYREQUEST['OB']),'</th>',
8061 + '<th>',sortheader('C','Avg. Hits', "&OB=".$MYREQUEST['OB']),'</th>',
8062 + '<th>',sortheader('A','Avg. Size', "&OB=".$MYREQUEST['OB']),'</th>',
8065 + // builds list with alpha numeric sortable keys
8067 + $tmp = $list = array();
8068 + foreach($cache[$scope_list[$MYREQUEST['SCOPE']]] as $entry) {
8069 + $n = dirname($entry['filename']);
8070 + if ($MYREQUEST['AGGR'] > 0) {
8071 + $n = preg_replace("!^(/?(?:[^/\\\\]+[/\\\\]){".($MYREQUEST['AGGR']-1)."}[^/\\\\]*).*!", "$1", $n);
8073 + if (!isset($tmp[$n])) {
8074 + $tmp[$n] = array('hits'=>0,'size'=>0,'ents'=>0);
8076 + $tmp[$n]['hits'] += $entry['num_hits'];
8077 + $tmp[$n]['size'] += $entry['mem_size'];
8078 + ++$tmp[$n]['ents'];
8081 + foreach ($tmp as $k => $v) {
8082 + switch($MYREQUEST['SORT1']) {
8083 + case 'A': $kn=sprintf('%015d-',$v['size'] / $v['ents']);break;
8084 + case 'T': $kn=sprintf('%015d-',$v['ents']); break;
8085 + case 'H': $kn=sprintf('%015d-',$v['hits']); break;
8086 + case 'Z': $kn=sprintf('%015d-',$v['size']); break;
8087 + case 'C': $kn=sprintf('%015d-',$v['hits'] / $v['ents']);break;
8088 + case 'S': $kn = $k; break;
8090 + $list[$kn.$k] = array($k, $v['ents'], $v['hits'], $v['size']);
8097 + switch ($MYREQUEST['SORT2']) {
8098 + case "A": krsort($list); break;
8099 + case "D": ksort($list); break;
8104 + foreach($list as $entry) {
8106 + '<tr class=tr-',$i%2,'>',
8107 + "<td class=td-0>",$entry[0],'</a></td>',
8108 + '<td class="td-n center">',$entry[1],'</td>',
8109 + '<td class="td-n center">',$entry[2],'</td>',
8110 + '<td class="td-n center">',$entry[3],'</td>',
8111 + '<td class="td-n center">',round($entry[2] / $entry[1]),'</td>',
8112 + '<td class="td-n center">',round($entry[3] / $entry[1]),'</td>',
8115 + if (++$i == $MYREQUEST['COUNT']) break;
8119 + echo '<tr class=tr-0><td class="center" colspan=6><i>No data</i></td></tr>';
8125 + if ($list && $i < count($list)) {
8126 + echo "<a href=\"$MY_SELF&OB=",$MYREQUEST['OB'],"&COUNT=0\"><i>",count($list)-$i,' more available...</i></a>';
8134 +// -----------------------------------------------
8136 +// -----------------------------------------------
8137 +case OB_VERSION_CHECK:
8139 + <div class="info"><h2>APC Version Information</h2>
8140 + <table cellspacing=0><tbody>
8146 + $rss = @file_get_contents("http://pecl.php.net/feeds/pkg_apc.rss");
8148 + echo '<tr class="td-last center"><td>Unable to fetch version information.</td></tr>';
8150 + $apcversion = phpversion('apc');
8152 + preg_match('!<title>APC ([0-9.]+)</title>!', $rss, $match);
8153 + echo '<tr class="tr-0 center"><td>';
8154 + if (version_compare($apcversion, $match[1], '>=')) {
8155 + echo '<div class="ok">You are running the latest version of APC ('.$apcversion.')</div>';
8158 + echo '<div class="failed">You are running an older version of APC ('.$apcversion.'),
8159 + newer version '.$match[1].' is available at <a href="http://pecl.php.net/package/APC/'.$match[1].'">
8160 + http://pecl.php.net/package/APC/'.$match[1].'</a>
8164 + echo '</td></tr>';
8165 + echo '<tr class="tr-0"><td><h3>Change Log:</h3><br/>';
8167 + preg_match_all('!<(title|description)>([^<]+)</\\1>!', $rss, $match);
8168 + next($match[2]); next($match[2]);
8170 + while (list(,$v) = each($match[2])) {
8171 + list(,$ver) = explode(' ', $v, 2);
8172 + if ($i < 0 && version_compare($apcversion, $ver, '>=')) {
8174 + } else if (!$i--) {
8177 + echo "<b><a href=\"http://pecl.php.net/package/APC/$ver\">".htmlspecialchars($v)."</a></b><br><blockquote>";
8178 + echo nl2br(htmlspecialchars(current($match[2])))."</blockquote>";
8181 + echo '</td></tr>';
8197 +<!-- <?php echo "\nBased on APCGUI By R.Becker\n$VERSION\n"?> -->
8200 diff -ruN php-5.1.6.old/ext/apc/apc_php.h php-5.1.6/ext/APC/apc_php.h
8201 --- php-5.1.6.old/ext/apc/apc_php.h 1969-12-31 18:00:00.000000000 -0600
8202 +++ php-5.1.6/ext/apc/apc_php.h 2007-04-02 18:05:30.000000000 -0500
8205 + +----------------------------------------------------------------------+
8207 + +----------------------------------------------------------------------+
8208 + | Copyright (c) 2006 The PHP Group |
8209 + +----------------------------------------------------------------------+
8210 + | This source file is subject to version 3.01 of the PHP license, |
8211 + | that is bundled with this package in the file LICENSE, and is |
8212 + | available through the world-wide-web at the following url: |
8213 + | http://www.php.net/license/3_01.txt |
8214 + | If you did not receive a copy of the PHP license and are unable to |
8215 + | obtain it through the world-wide-web, please send a note to |
8216 + | license@php.net so we can mail you a copy immediately. |
8217 + +----------------------------------------------------------------------+
8218 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
8219 + | George Schlossnagle <george@omniti.com> |
8220 + | Rasmus Lerdorf <rasmus@php.net> |
8221 + | Arun C. Murthy <arunc@yahoo-inc.com> |
8222 + | Gopal Vijayaraghavan <gopalv@yahoo-inc.com> |
8223 + +----------------------------------------------------------------------+
8225 + This software was contributed to PHP by Community Connect Inc. in 2002
8226 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
8227 + Future revisions and derivatives of this source code must acknowledge
8228 + Community Connect Inc. as the original contributor of this module by
8229 + leaving this note intact in the source code.
8231 + All other licensing and usage conditions are those of the PHP Group.
8235 +/* $Id: apc_php.h,v 3.10 2006/11/16 20:24:48 gopalv Exp $ */
8241 + * The purpose of this header file is to include all PHP and Zend headers that
8242 + * are typically needed elsewhere in APC. This makes it easy to insure that
8243 + * all required headers are available.
8248 +#include "zend_API.h"
8249 +#include "zend_compile.h"
8250 +#include "zend_hash.h"
8251 +#include "zend_extensions.h"
8253 +#if ZEND_MODULE_API_NO > 20050922
8254 +#define ZEND_ENGINE_2_2
8256 +#if ZEND_MODULE_API_NO > 20050921
8257 +#define ZEND_ENGINE_2_1
8259 +#ifdef ZEND_ENGINE_2_1
8260 +#include "zend_vm.h"
8263 +#include "rfc1867.h"
8268 + * Local variables:
8270 + * c-basic-offset: 4
8272 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
8273 + * vim<600: expandtab sw=4 ts=4 sts=4
8275 diff -ruN php-5.1.6.old/ext/apc/apc_pthreadmutex.c php-5.1.6/ext/APC/apc_pthreadmutex.c
8276 --- php-5.1.6.old/ext/apc/apc_pthreadmutex.c 1969-12-31 18:00:00.000000000 -0600
8277 +++ php-5.1.6/ext/apc/apc_pthreadmutex.c 2007-04-02 18:05:30.000000000 -0500
8280 + +----------------------------------------------------------------------+
8282 + +----------------------------------------------------------------------+
8283 + | Copyright (c) 2006 The PHP Group |
8284 + +----------------------------------------------------------------------+
8285 + | This source file is subject to version 3.01 of the PHP license, |
8286 + | that is bundled with this package in the file LICENSE, and is |
8287 + | available through the world-wide-web at the following url: |
8288 + | http://www.php.net/license/3_01.txt |
8289 + | If you did not receive a copy of the PHP license and are unable to |
8290 + | obtain it through the world-wide-web, please send a note to |
8291 + | license@php.net so we can mail you a copy immediately. |
8292 + +----------------------------------------------------------------------+
8293 + | Authors: Brian Shire <shire@php.net> |
8294 + +----------------------------------------------------------------------+
8298 +/* $Id: apc_pthreadmutex.c,v 3.2 2007/02/15 21:40:45 shire Exp $ */
8300 +#include "apc_pthreadmutex.h"
8302 +#ifdef APC_PTHREADMUTEX_LOCKS
8304 +pthread_mutex_t *apc_pthreadmutex_create(pthread_mutex_t *lock)
8307 + pthread_mutexattr_t* attr;
8308 + attr = malloc(sizeof(pthread_mutexattr_t));
8310 + result = pthread_mutexattr_init(attr);
8311 + if(result == ENOMEM) {
8312 + apc_eprint("pthread mutex error: Insufficient memory exists to create the mutex attribute object.");
8313 + } else if(result == EINVAL) {
8314 + apc_eprint("pthread mutex error: attr does not point to writeable memory.");
8315 + } else if(result == EFAULT) {
8316 + apc_eprint("pthread mutex error: attr is an invalid pointer.");
8319 + /* pthread_mutexattr_settype(attr, PTHREAD_MUTEX_ERRORCHECK); */
8320 + result = pthread_mutexattr_setpshared(attr, PTHREAD_PROCESS_SHARED);
8321 + if(result == EINVAL) {
8322 + apc_eprint("pthread mutex error: attr is not an initialized mutex attribute object, or pshared is not a valid process-shared state setting.");
8323 + } else if(result == EFAULT) {
8324 + apc_eprint("pthread mutex error: attr is an invalid pointer.");
8325 + } else if(result == ENOTSUP) {
8326 + apc_eprint("pthread mutex error: pshared was set to PTHREAD_PROCESS_SHARED.");
8329 + if(pthread_mutex_init(lock, attr)) {
8330 + apc_eprint("unable to initialize pthread lock");
8335 +void apc_pthreadmutex_destroy(pthread_mutex_t *lock)
8337 + return; /* we don't actually destroy the mutex, as it would destroy it for all processes */
8340 +void apc_pthreadmutex_lock(pthread_mutex_t *lock)
8343 + result = pthread_mutex_lock(lock);
8344 + if(result == EINVAL) {
8345 + apc_eprint("unable to obtain pthread lock (EINVAL)");
8346 + } else if(result == EDEADLK) {
8347 + apc_eprint("unable to obtain pthread lock (EDEADLK)");
8351 +void apc_pthreadmutex_unlock(pthread_mutex_t *lock)
8353 + if(pthread_mutex_unlock(lock)) {
8354 + apc_eprint("unable to unlock pthread lock");
8358 +zend_bool apc_pthreadmutex_nonblocking_lock(pthread_mutex_t *lock)
8361 + rval = pthread_mutex_trylock(lock);
8362 + if(rval == EBUSY) { /* Lock is already held */
8364 + } else if(rval == 0) { /* Obtained lock */
8366 + } else { /* Other error */
8367 + apc_eprint("unable to obtain pthread trylock");
8376 + * Local variables:
8378 + * c-basic-offset: 4
8380 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
8381 + * vim<600: expandtab sw=4 ts=4 sts=4
8383 diff -ruN php-5.1.6.old/ext/apc/apc_pthreadmutex.h php-5.1.6/ext/APC/apc_pthreadmutex.h
8384 --- php-5.1.6.old/ext/apc/apc_pthreadmutex.h 1969-12-31 18:00:00.000000000 -0600
8385 +++ php-5.1.6/ext/apc/apc_pthreadmutex.h 2007-04-02 18:05:30.000000000 -0500
8388 + +----------------------------------------------------------------------+
8390 + +----------------------------------------------------------------------+
8391 + | Copyright (c) 2006 The PHP Group |
8392 + +----------------------------------------------------------------------+
8393 + | This source file is subject to version 3.01 of the PHP license, |
8394 + | that is bundled with this package in the file LICENSE, and is |
8395 + | available through the world-wide-web at the following url: |
8396 + | http://www.php.net/license/3_01.txt |
8397 + | If you did not receive a copy of the PHP license and are unable to |
8398 + | obtain it through the world-wide-web, please send a note to |
8399 + | license@php.net so we can mail you a copy immediately. |
8400 + +----------------------------------------------------------------------+
8401 + | Authors: Brian Shire <shire@php.net> |
8402 + +----------------------------------------------------------------------+
8406 +/* $Id: apc_pthreadmutex.h,v 3.3 2007/01/28 07:53:57 shire Exp $ */
8408 +#ifndef APC_PTHREADMUTEX_H
8409 +#define APC_PTHREADMUTEX_H
8413 +#ifdef APC_PTHREADMUTEX_LOCKS
8415 +#include <pthread.h>
8417 +pthread_mutex_t *apc_pthreadmutex_create();
8418 +void apc_pthreadmutex_destroy(pthread_mutex_t *lock);
8419 +void apc_pthreadmutex_lock(pthread_mutex_t *lock);
8420 +void apc_pthreadmutex_unlock(pthread_mutex_t *lock);
8421 +zend_bool apc_pthreadmutex_nonblocking_lock(pthread_mutex_t *lock);
8428 + * Local variables:
8430 + * c-basic-offset: 4
8432 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
8433 + * vim<600: expandtab sw=4 ts=4 sts=4
8435 diff -ruN php-5.1.6.old/ext/apc/apc_rfc1867.c php-5.1.6/ext/APC/apc_rfc1867.c
8436 --- php-5.1.6.old/ext/apc/apc_rfc1867.c 1969-12-31 18:00:00.000000000 -0600
8437 +++ php-5.1.6/ext/apc/apc_rfc1867.c 2007-04-02 18:05:30.000000000 -0500
8440 + +----------------------------------------------------------------------+
8442 + +----------------------------------------------------------------------+
8443 + | Copyright (c) 2006 The PHP Group |
8444 + +----------------------------------------------------------------------+
8445 + | This source file is subject to version 3.01 of the PHP license, |
8446 + | that is bundled with this package in the file LICENSE, and is |
8447 + | available through the world-wide-web at the following url: |
8448 + | http://www.php.net/license/3_01.txt |
8449 + | If you did not receive a copy of the PHP license and are unable to |
8450 + | obtain it through the world-wide-web, please send a note to |
8451 + | license@php.net so we can mail you a copy immediately. |
8452 + +----------------------------------------------------------------------+
8453 + | Authors: Rasmus Lerdorf <rasmus@php.net> |
8454 + +----------------------------------------------------------------------+
8456 + This software was contributed to PHP by Community Connect Inc. in 2002
8457 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
8458 + Future revisions and derivatives of this source code must acknowledge
8459 + Community Connect Inc. as the original contributor of this module by
8460 + leaving this note intact in the source code.
8462 + All other licensing and usage conditions are those of the PHP Group.
8466 +/* $Id: apc_rfc1867.c,v 3.4 2007/02/24 11:45:29 rasmus Exp $*/
8469 +#include "rfc1867.h"
8471 +#ifdef MULTIPART_EVENT_FORMDATA
8472 +extern int _apc_store(char *strkey, int strkey_len, const zval *val, const unsigned int ttl, const int exclusive TSRMLS_DC);
8474 +static double my_time() {
8477 + gettimeofday(&a, NULL);
8478 + t = a.tv_sec + (a.tv_usec/1000000);
8482 +void apc_rfc1867_progress(unsigned int event, void *event_data, void **extra TSRMLS_DC) {
8483 + static char tracking_key[64];
8484 + static int key_length = 0;
8485 + static size_t content_length = 0;
8486 + static char filename[128];
8487 + static char name[64];
8488 + static char *temp_filename=NULL;
8489 + static int cancel_upload = 0;
8490 + static double start_time;
8491 + static size_t bytes_processed = 0;
8492 + static double rate;
8493 + zval *track = NULL;
8496 + case MULTIPART_EVENT_START:
8498 + multipart_event_start *data = (multipart_event_start *) event_data;
8499 + content_length = data->content_length;
8500 + *tracking_key = '\0';
8502 + cancel_upload = 0;
8503 + temp_filename = NULL;
8506 + start_time = my_time();
8507 + bytes_processed = 0;
8512 + case MULTIPART_EVENT_FORMDATA:
8514 + multipart_event_formdata *data = (multipart_event_formdata *) event_data;
8516 + if(data->name && !strncasecmp(data->name,"apc_upload_progress",19) && data->value && data->length && data->length < 58) {
8517 + strlcat(tracking_key, "upload_", 63);
8518 + strlcat(tracking_key, *data->value, 63);
8519 + key_length = data->length+7;
8520 + bytes_processed = data->post_bytes_processed;
8525 + case MULTIPART_EVENT_FILE_START:
8526 + if(*tracking_key) {
8527 + multipart_event_file_start *data = (multipart_event_file_start *) event_data;
8529 + bytes_processed = data->post_bytes_processed;
8530 + strncpy(filename,*data->filename,127);
8531 + temp_filename = NULL;
8532 + strncpy(name,data->name,63);
8533 + ALLOC_INIT_ZVAL(track);
8534 + array_init(track);
8535 + add_assoc_long(track, "total", content_length);
8536 + add_assoc_long(track, "current", bytes_processed);
8537 + add_assoc_string(track, "filename", filename, 1);
8538 + add_assoc_string(track, "name", name, 1);
8539 + add_assoc_long(track, "done", 0);
8540 + _apc_store(tracking_key, key_length, track, 3600, 0 TSRMLS_CC);
8541 + zval_ptr_dtor(&track);
8545 + case MULTIPART_EVENT_FILE_DATA:
8546 + if(*tracking_key) {
8547 + multipart_event_file_data *data = (multipart_event_file_data *) event_data;
8548 + bytes_processed = data->post_bytes_processed;
8549 + ALLOC_INIT_ZVAL(track);
8550 + array_init(track);
8551 + add_assoc_long(track, "total", content_length);
8552 + add_assoc_long(track, "current", bytes_processed);
8553 + add_assoc_string(track, "filename", filename, 1);
8554 + add_assoc_string(track, "name", name, 1);
8555 + add_assoc_long(track, "done", 0);
8556 + _apc_store(tracking_key, key_length, track, 3600, 0 TSRMLS_CC);
8557 + zval_ptr_dtor(&track);
8561 + case MULTIPART_EVENT_FILE_END:
8562 + if(*tracking_key) {
8563 + multipart_event_file_end *data = (multipart_event_file_end *) event_data;
8564 + bytes_processed = data->post_bytes_processed;
8565 + cancel_upload = data->cancel_upload;
8566 + temp_filename = data->temp_filename;
8567 + ALLOC_INIT_ZVAL(track);
8568 + array_init(track);
8569 + add_assoc_long(track, "total", content_length);
8570 + add_assoc_long(track, "current", bytes_processed);
8571 + add_assoc_string(track, "filename", filename, 1);
8572 + add_assoc_string(track, "name", name, 1);
8573 + add_assoc_string(track, "temp_filename", temp_filename, 1);
8574 + add_assoc_long(track, "cancel_upload", cancel_upload);
8575 + add_assoc_long(track, "done", 0);
8576 + _apc_store(tracking_key, key_length, track, 3600, 0 TSRMLS_CC);
8577 + zval_ptr_dtor(&track);
8581 + case MULTIPART_EVENT_END:
8582 + if(*tracking_key) {
8583 + double now = my_time();
8584 + multipart_event_end *data = (multipart_event_end *) event_data;
8585 + bytes_processed = data->post_bytes_processed;
8586 + if(now>start_time) rate = 8.0*bytes_processed/(now-start_time);
8587 + else rate = 8.0*bytes_processed; /* Too quick */
8588 + ALLOC_INIT_ZVAL(track);
8589 + array_init(track);
8590 + add_assoc_long(track, "total", content_length);
8591 + add_assoc_long(track, "current", bytes_processed);
8592 + add_assoc_double(track, "rate", rate);
8593 + add_assoc_string(track, "filename", filename, 1);
8594 + add_assoc_string(track, "name", name, 1);
8595 + add_assoc_string(track, "temp_filename", temp_filename, 1);
8596 + add_assoc_long(track, "cancel_upload", cancel_upload);
8597 + add_assoc_long(track, "done", 1);
8598 + _apc_store(tracking_key, key_length, track, 3600, 0 TSRMLS_CC);
8599 + zval_ptr_dtor(&track);
8607 + * Local variables:
8609 + * c-basic-offset: 4
8611 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
8612 + * vim<600: expandtab sw=4 ts=4 sts=4
8614 diff -ruN php-5.1.6.old/ext/apc/apc_sem.c php-5.1.6/ext/APC/apc_sem.c
8615 --- php-5.1.6.old/ext/apc/apc_sem.c 1969-12-31 18:00:00.000000000 -0600
8616 +++ php-5.1.6/ext/apc/apc_sem.c 2007-04-02 18:05:30.000000000 -0500
8619 + +----------------------------------------------------------------------+
8621 + +----------------------------------------------------------------------+
8622 + | Copyright (c) 2006 The PHP Group |
8623 + +----------------------------------------------------------------------+
8624 + | This source file is subject to version 3.01 of the PHP license, |
8625 + | that is bundled with this package in the file LICENSE, and is |
8626 + | available through the world-wide-web at the following url: |
8627 + | http://www.php.net/license/3_01.txt |
8628 + | If you did not receive a copy of the PHP license and are unable to |
8629 + | obtain it through the world-wide-web, please send a note to |
8630 + | license@php.net so we can mail you a copy immediately. |
8631 + +----------------------------------------------------------------------+
8632 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
8633 + +----------------------------------------------------------------------+
8635 + This software was contributed to PHP by Community Connect Inc. in 2002
8636 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
8637 + Future revisions and derivatives of this source code must acknowledge
8638 + Community Connect Inc. as the original contributor of this module by
8639 + leaving this note intact in the source code.
8641 + All other licensing and usage conditions are those of the PHP Group.
8645 +/* $Id: apc_sem.c,v 3.16 2006/03/12 00:31:45 rasmus Exp $ */
8647 +#include "apc_sem.h"
8650 +#include <sys/types.h>
8651 +#include <sys/ipc.h>
8652 +#include <sys/sem.h>
8653 +#include <sys/stat.h>
8654 +#include <unistd.h>
8657 +/* we have semun, no need to define */
8661 + int val; /* value for SETVAL */
8662 + struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */
8663 + unsigned short *array; /* array for GETALL, SETALL */
8664 + /* Linux specific part: */
8665 + struct seminfo *__buf; /* buffer for IPC_INFO */
8667 +#define HAVE_SEMUN 1
8671 +# define SEM_R 0444
8674 +# define SEM_A 0222
8677 +/* always use SEM_UNDO, otherwise we risk deadlock */
8678 +#define USE_SEM_UNDO
8680 +#ifdef USE_SEM_UNDO
8681 +# define UNDO SEM_UNDO
8686 +int apc_sem_create(const char* pathname, int proj, int initval)
8695 + key = IPC_PRIVATE;
8696 + if (pathname != NULL) {
8697 + if ((key = ftok(pathname, proj)) < 0) {
8698 + apc_eprint("apc_sem_create: ftok(%s,%d) failed:", pathname, proj);
8702 + if ((semid = semget(key, 1, IPC_CREAT | IPC_EXCL | perms)) >= 0) {
8703 + /* sempahore created for the first time, initialize now */
8704 + arg.val = initval;
8705 + if (semctl(semid, 0, SETVAL, arg) < 0) {
8706 + apc_eprint("apc_sem_create: semctl(%d,...) failed:", semid);
8709 + else if (errno == EEXIST) {
8710 + /* sempahore already exists, don't initialize */
8711 + if ((semid = semget(key, 1, perms)) < 0) {
8712 + apc_eprint("apc_sem_create: semget(%u,...) failed:", key);
8714 + /* insert <sleazy way to avoid race condition> here */
8717 + apc_eprint("apc_sem_create: semget(%u,...) failed:", key);
8723 +void apc_sem_destroy(int semid)
8725 + /* we expect this call to fail often, so we do not check */
8727 + semctl(semid, 0, IPC_RMID, arg);
8730 +void apc_sem_lock(int semid)
8736 + op.sem_flg = UNDO;
8738 + if (semop(semid, &op, 1) < 0) {
8739 + if (errno != EINTR) {
8740 + apc_eprint("apc_sem_lock: semop(%d) failed:", semid);
8745 +void apc_sem_unlock(int semid)
8751 + op.sem_flg = UNDO;
8753 + if (semop(semid, &op, 1) < 0) {
8754 + if (errno != EINTR) {
8755 + apc_eprint("apc_sem_unlock: semop(%d) failed:", semid);
8760 +void apc_sem_wait_for_zero(int semid)
8766 + op.sem_flg = UNDO;
8768 + if (semop(semid, &op, 1) < 0) {
8769 + if (errno != EINTR) {
8770 + apc_eprint("apc_sem_waitforzero: semop(%d) failed:", semid);
8775 +int apc_sem_get_value(int semid)
8778 + unsigned short val[1];
8781 + if (semctl(semid, 0, GETALL, arg) < 0) {
8782 + apc_eprint("apc_sem_getvalue: semctl(%d,...) failed:", semid);
8788 + * Local variables:
8790 + * c-basic-offset: 4
8792 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
8793 + * vim<600: expandtab sw=4 ts=4 sts=4
8795 diff -ruN php-5.1.6.old/ext/apc/apc_sem.h php-5.1.6/ext/APC/apc_sem.h
8796 --- php-5.1.6.old/ext/apc/apc_sem.h 1969-12-31 18:00:00.000000000 -0600
8797 +++ php-5.1.6/ext/apc/apc_sem.h 2007-04-02 18:05:30.000000000 -0500
8800 + +----------------------------------------------------------------------+
8802 + +----------------------------------------------------------------------+
8803 + | Copyright (c) 2006 The PHP Group |
8804 + +----------------------------------------------------------------------+
8805 + | This source file is subject to version 3.01 of the PHP license, |
8806 + | that is bundled with this package in the file LICENSE, and is |
8807 + | available through the world-wide-web at the following url: |
8808 + | http://www.php.net/license/3_01.txt |
8809 + | If you did not receive a copy of the PHP license and are unable to |
8810 + | obtain it through the world-wide-web, please send a note to |
8811 + | license@php.net so we can mail you a copy immediately. |
8812 + +----------------------------------------------------------------------+
8813 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
8814 + +----------------------------------------------------------------------+
8816 + This software was contributed to PHP by Community Connect Inc. in 2002
8817 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
8818 + Future revisions and derivatives of this source code must acknowledge
8819 + Community Connect Inc. as the original contributor of this module by
8820 + leaving this note intact in the source code.
8822 + All other licensing and usage conditions are those of the PHP Group.
8826 +/* $Id: apc_sem.h,v 3.6 2006/03/12 00:31:45 rasmus Exp $ */
8831 +/* Wrapper functions for SysV sempahores */
8833 +extern int apc_sem_create(const char* pathname, int proj, int initval);
8834 +extern void apc_sem_destroy(int semid);
8835 +extern void apc_sem_lock(int semid);
8836 +extern void apc_sem_unlock(int semid);
8837 +extern void apc_sem_wait_for_zero(int semid);
8838 +extern int apc_sem_get_value(int semid);
8843 + * Local variables:
8845 + * c-basic-offset: 4
8847 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
8848 + * vim<600: expandtab sw=4 ts=4 sts=4
8850 diff -ruN php-5.1.6.old/ext/apc/apc_shm.c php-5.1.6/ext/APC/apc_shm.c
8851 --- php-5.1.6.old/ext/apc/apc_shm.c 1969-12-31 18:00:00.000000000 -0600
8852 +++ php-5.1.6/ext/apc/apc_shm.c 2007-04-02 18:05:30.000000000 -0500
8855 + +----------------------------------------------------------------------+
8857 + +----------------------------------------------------------------------+
8858 + | Copyright (c) 2006 The PHP Group |
8859 + +----------------------------------------------------------------------+
8860 + | This source file is subject to version 3.01 of the PHP license, |
8861 + | that is bundled with this package in the file LICENSE, and is |
8862 + | available through the world-wide-web at the following url: |
8863 + | http://www.php.net/license/3_01.txt |
8864 + | If you did not receive a copy of the PHP license and are unable to |
8865 + | obtain it through the world-wide-web, please send a note to |
8866 + | license@php.net so we can mail you a copy immediately. |
8867 + +----------------------------------------------------------------------+
8868 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
8869 + | Rasmus Lerdorf <rasmus@php.net> |
8870 + +----------------------------------------------------------------------+
8872 + This software was contributed to PHP by Community Connect Inc. in 2002
8873 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
8874 + Future revisions and derivatives of this source code must acknowledge
8875 + Community Connect Inc. as the original contributor of this module by
8876 + leaving this note intact in the source code.
8878 + All other licensing and usage conditions are those of the PHP Group.
8882 +/* $Id: apc_shm.c,v 3.10 2006/05/31 22:24:48 rasmus Exp $ */
8884 +#include "apc_shm.h"
8886 +#include <sys/types.h>
8888 +/* shm functions are available in TSRM */
8889 +#include <tsrm/tsrm_win32.h>
8892 +#include <sys/ipc.h>
8893 +#include <sys/shm.h>
8894 +#include <sys/stat.h>
8898 +# define SHM_R 0444 /* read permission */
8901 +# define SHM_A 0222 /* write permission */
8904 +int apc_shm_create(const char* pathname, int proj, int size)
8906 + int shmid; /* shared memory id */
8907 + int oflag; /* permissions on shm */
8908 + key_t key; /* shm key returned by ftok */
8910 + key = IPC_PRIVATE;
8912 + /* no ftok yet for win32 */
8913 + if (pathname != NULL) {
8914 + if ((key = ftok(pathname, proj)) < 0) {
8915 + apc_eprint("apc_shm_create: ftok failed:");
8920 + oflag = IPC_CREAT | SHM_R | SHM_A;
8921 + if ((shmid = shmget(key, size, oflag)) < 0) {
8922 + apc_eprint("apc_shm_create: shmget(%d, %d, %d) failed: %s. It is possible that the chosen SHM segment size is higher than the operation system allows. Linux has usually a default limit of 32MB per segment.", key, size, oflag, strerror(errno));
8928 +void apc_shm_destroy(int shmid)
8930 + /* we expect this call to fail often, so we do not check */
8931 + shmctl(shmid, IPC_RMID, 0);
8934 +void* apc_shm_attach(int shmid)
8936 + void* shmaddr; /* the shared memory address */
8938 + if ((int)(shmaddr = shmat(shmid, 0, 0)) == -1) {
8939 + apc_eprint("apc_shm_attach: shmat failed:");
8943 + * We set the shmid for removal immediately after attaching to it. The
8944 + * segment won't disappear until all processes have detached from it.
8946 + apc_shm_destroy(shmid);
8950 +void apc_shm_detach(void* shmaddr)
8952 + if (shmdt(shmaddr) < 0) {
8953 + apc_eprint("apc_shm_detach: shmdt failed:");
8958 + * Local variables:
8960 + * c-basic-offset: 4
8962 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
8963 + * vim<600: expandtab sw=4 ts=4 sts=4
8965 diff -ruN php-5.1.6.old/ext/apc/apc_shm.h php-5.1.6/ext/APC/apc_shm.h
8966 --- php-5.1.6.old/ext/apc/apc_shm.h 1969-12-31 18:00:00.000000000 -0600
8967 +++ php-5.1.6/ext/apc/apc_shm.h 2007-04-02 18:05:30.000000000 -0500
8970 + +----------------------------------------------------------------------+
8972 + +----------------------------------------------------------------------+
8973 + | Copyright (c) 2006 The PHP Group |
8974 + +----------------------------------------------------------------------+
8975 + | This source file is subject to version 3.01 of the PHP license, |
8976 + | that is bundled with this package in the file LICENSE, and is |
8977 + | available through the world-wide-web at the following url: |
8978 + | http://www.php.net/license/3_01.txt |
8979 + | If you did not receive a copy of the PHP license and are unable to |
8980 + | obtain it through the world-wide-web, please send a note to |
8981 + | license@php.net so we can mail you a copy immediately. |
8982 + +----------------------------------------------------------------------+
8983 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
8984 + +----------------------------------------------------------------------+
8986 + This software was contributed to PHP by Community Connect Inc. in 2002
8987 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
8988 + Future revisions and derivatives of this source code must acknowledge
8989 + Community Connect Inc. as the original contributor of this module by
8990 + leaving this note intact in the source code.
8992 + All other licensing and usage conditions are those of the PHP Group.
8996 +/* $Id: apc_shm.h,v 3.6 2006/03/12 00:31:45 rasmus Exp $ */
9001 +/* Wrapper functions for unix shared memory */
9003 +extern int apc_shm_create(const char* name, int proj, int size);
9004 +extern void apc_shm_destroy(int shmid);
9005 +extern void* apc_shm_attach(int shmid);
9006 +extern void apc_shm_detach(void* shmaddr);
9011 + * Local variables:
9013 + * c-basic-offset: 4
9015 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
9016 + * vim<600: expandtab sw=4 ts=4 sts=4
9018 diff -ruN php-5.1.6.old/ext/apc/apc_sma.c php-5.1.6/ext/APC/apc_sma.c
9019 --- php-5.1.6.old/ext/apc/apc_sma.c 1969-12-31 18:00:00.000000000 -0600
9020 +++ php-5.1.6/ext/apc/apc_sma.c 2007-04-02 18:05:30.000000000 -0500
9023 + +----------------------------------------------------------------------+
9025 + +----------------------------------------------------------------------+
9026 + | Copyright (c) 2006 The PHP Group |
9027 + +----------------------------------------------------------------------+
9028 + | This source file is subject to version 3.01 of the PHP license, |
9029 + | that is bundled with this package in the file LICENSE, and is |
9030 + | available through the world-wide-web at the following url: |
9031 + | http://www.php.net/license/3_01.txt |
9032 + | If you did not receive a copy of the PHP license and are unable to |
9033 + | obtain it through the world-wide-web, please send a note to |
9034 + | license@php.net so we can mail you a copy immediately. |
9035 + +----------------------------------------------------------------------+
9036 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
9037 + | Rasmus Lerdorf <rasmus@php.net> |
9038 + +----------------------------------------------------------------------+
9040 + This software was contributed to PHP by Community Connect Inc. in 2002
9041 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
9042 + Future revisions and derivatives of this source code must acknowledge
9043 + Community Connect Inc. as the original contributor of this module by
9044 + leaving this note intact in the source code.
9046 + All other licensing and usage conditions are those of the PHP Group.
9050 +/* $Id: apc_sma.c,v 1.63 2007/04/02 09:02:57 gopalv Exp $ */
9052 +#include "apc_sma.h"
9054 +#include "apc_globals.h"
9055 +#include "apc_lock.h"
9056 +#include "apc_shm.h"
9057 +#include <limits.h>
9059 +void *apc_mmap(char *file_mask, int size);
9060 +void apc_unmap(void* shmaddr, int size);
9063 +/* {{{ locking macros */
9064 +#define LOCK(c) { HANDLE_BLOCK_INTERRUPTIONS(); apc_lck_lock(c); }
9065 +#define RDLOCK(c) { HANDLE_BLOCK_INTERRUPTIONS(); apc_lck_rdlock(c); }
9066 +#define UNLOCK(c) { apc_lck_unlock(c); HANDLE_UNBLOCK_INTERRUPTIONS(); }
9069 +enum { DEFAULT_NUMSEG=1, DEFAULT_SEGSIZE=30*1024*1024 };
9071 +static int sma_initialized = 0; /* true if the sma has been initialized */
9072 +static unsigned int sma_numseg; /* number of shm segments to allow */
9073 +static size_t sma_segsize; /* size of each shm segment */
9074 +static int* sma_segments; /* array of shm segment ids */
9075 +static void** sma_shmaddrs; /* array of shm segment addresses */
9076 +static int sma_lastseg = 0; /* index of MRU segment */
9078 +typedef struct header_t header_t;
9080 + apc_lck_t sma_lock; /* segment lock, MUST BE ALIGNED for futex locks */
9081 + size_t segsize; /* size of entire segment */
9082 + size_t avail; /* bytes available (not necessarily contiguous) */
9083 + size_t nfoffset; /* start next fit search from this offset */
9084 +#if ALLOC_DISTRIBUTION
9090 +/* do not enable for threaded http servers */
9091 +/* #define __APC_SMA_DEBUG__ 1 */
9093 +#ifdef __APC_SMA_DEBUG__
9094 +/* global counter for identifying blocks
9095 + * Technically it is possible to do the same
9096 + * using offsets, but double allocations of the
9097 + * same offset can happen. */
9098 +static volatile size_t block_id = 0;
9101 +#define APC_SMA_CANARIES 1
9103 +typedef struct block_t block_t;
9105 + size_t size; /* size of this block */
9106 + size_t next; /* offset in segment of next free block */
9107 +#ifdef APC_SMA_CANARIES
9108 + size_t canary; /* canary to check for memory overwrites */
9110 +#ifdef __APC_SMA_DEBUG__
9111 + size_t id; /* identifier for the memory block */
9115 +/* The macros BLOCKAT and OFFSET are used for convenience throughout this
9116 + * module. Both assume the presence of a variable shmaddr that points to the
9117 + * beginning of the shared memory segment in question. */
9119 +#define BLOCKAT(offset) ((block_t*)((char *)shmaddr + offset))
9120 +#define OFFSET(block) ((size_t)(((char*)block) - (char*)shmaddr))
9122 +/* Canary macros for setting, checking and resetting memory canaries */
9123 +#ifdef APC_SMA_CANARIES
9124 + #define SET_CANARY(v) (v)->canary = 0x42424242
9125 + #define CHECK_CANARY(v) assert((v)->canary == 0x42424242)
9126 + #define RESET_CANARY(v) (v)->canary = -42
9128 + #define SET_CANARY(v)
9129 + #define CHECK_CANARY(v)
9130 + #define RESET_CANARY(v)
9137 +#define max(a, b) ((a) > (b) ? (a) : (b))
9139 +/* {{{ ALIGNWORD: pad up x, aligned to the system's word boundary */
9140 +typedef union { void* p; int i; long l; double d; void (*f)(); } apc_word_t;
9141 +#define ALIGNWORD(x) (sizeof(apc_word_t) * (1 + (((x)-1)/sizeof(apc_word_t))))
9142 +#define MINBLOCKSIZE (ALIGNWORD(1) + ALIGNWORD(sizeof(block_t)))
9145 +/* {{{ sma_allocate: tries to allocate size bytes in a segment */
9146 +static int sma_allocate(void* shmaddr, size_t size)
9148 + header_t* header; /* header of shared memory segment */
9149 + block_t* prv; /* block prior to working block */
9150 + block_t* cur; /* working block in list */
9151 + block_t* prvnextfit; /* block before next fit */
9152 + size_t realsize; /* actual size of block needed, including header */
9153 + size_t last_offset; /* save the last search offset */
9155 + const size_t block_size = ALIGNWORD(sizeof(struct block_t));
9157 + realsize = ALIGNWORD(size + block_size);
9160 + * First, insure that the segment contains at least realsize free bytes,
9161 + * even if they are not contiguous.
9163 + header = (header_t*) shmaddr;
9164 + if (header->avail < realsize) {
9168 + prvnextfit = 0; /* initially null (no fit) */
9171 + /* If we have a next fit offset, start searching from there */
9172 + if(header->nfoffset) {
9173 + prv = BLOCKAT(header->nfoffset);
9175 + prv = BLOCKAT(sizeof(header_t));
9178 + CHECK_CANARY(prv);
9180 + while (prv->next != header->nfoffset) {
9181 + cur = BLOCKAT(prv->next);
9182 +#ifdef __APC_SMA_DEBUG__
9183 + CHECK_CANARY(cur);
9185 + /* If it can fit realiszie bytes in cur block, stop searching */
9186 + if (cur->size >= realsize) {
9190 + last_offset = prv->next;
9192 + if(wrapped && (prv->next >= header->nfoffset)) break;
9194 + /* Check to see if we need to wrap around and search from the top */
9195 + if(header->nfoffset && prv->next == 0) {
9196 + prv = BLOCKAT(sizeof(header_t));
9197 +#ifdef __APC_SMA_DEBUG__
9198 + CHECK_CANARY(prv);
9205 + if (prvnextfit == 0) {
9206 + header->nfoffset = 0;
9211 + cur = BLOCKAT(prv->next);
9213 + CHECK_CANARY(prv);
9214 + CHECK_CANARY(cur);
9216 + if (cur->size == realsize || (cur->size > realsize && cur->size < (realsize + (MINBLOCKSIZE * 2)))) {
9217 + /* cur is big enough for realsize, but too small to split - unlink it */
9218 + prv->next = cur->next;
9221 + block_t* nxt; /* the new block (chopped part of cur) */
9222 + size_t nxtoffset; /* offset of the block currently after cur */
9223 + size_t oldsize; /* size of cur before split */
9225 + /* nextfit is too big; split it into two smaller blocks */
9226 + nxtoffset = cur->next;
9227 + oldsize = cur->size;
9228 + prv->next += realsize; /* skip over newly allocated block */
9229 + cur->size = realsize; /* Set the size of this new block */
9230 + nxt = BLOCKAT(prv->next);
9231 + nxt->next = nxtoffset; /* Re-link the shortened block */
9232 + nxt->size = oldsize - realsize; /* and fix the size */
9234 +#ifdef __APC_SMA_DEBUG__
9239 + /* update the block header */
9240 + header->avail -= cur->size;
9241 +#if ALLOC_DISTRIBUTION
9242 + header->adist[(int)(log(size)/log(2))]++;
9245 + header->nfoffset = last_offset;
9248 +#ifdef __APC_SMA_DEBUG__
9249 + cur->id = ++block_id;
9250 + fprintf(stderr, "allocate(realsize=%d,size=%d,id=%d)\n", (int)(size), (int)(cur->size), cur->id);
9253 + return OFFSET(cur) + block_size;
9257 +/* {{{ sma_deallocate: deallocates the block at the given offset */
9258 +static int sma_deallocate(void* shmaddr, int offset)
9260 + header_t* header; /* header of shared memory segment */
9261 + block_t* cur; /* the new block to insert */
9262 + block_t* prv; /* the block before cur */
9263 + block_t* nxt; /* the block after cur */
9264 + size_t size; /* size of deallocated block */
9266 + offset -= ALIGNWORD(sizeof(struct block_t));
9267 + assert(offset >= 0);
9269 + /* find position of new block in free list */
9270 + cur = BLOCKAT(offset);
9271 + prv = BLOCKAT(sizeof(header_t));
9273 + CHECK_CANARY(cur);
9275 +#ifdef __APC_SMA_DEBUG__
9276 + CHECK_CANARY(prv);
9277 + fprintf(stderr, "free(%p, size=%d,id=%d)\n", cur, (int)(cur->size), cur->id);
9279 + while (prv->next != 0 && prv->next < offset) {
9280 + prv = BLOCKAT(prv->next);
9281 +#ifdef __APC_SMA_DEBUG__
9282 + CHECK_CANARY(prv);
9286 + CHECK_CANARY(prv);
9288 + /* insert new block after prv */
9289 + cur->next = prv->next;
9290 + prv->next = offset;
9292 +#ifdef __APC_SMA_DEBUG__
9293 + CHECK_CANARY(cur);
9297 + /* update the block header */
9298 + header = (header_t*) shmaddr;
9299 + header->avail += cur->size;
9302 + if (((char *)prv) + prv->size == (char *) cur) {
9303 + /* cur and prv share an edge, combine them */
9304 + prv->size += cur->size;
9305 + prv->next = cur->next;
9306 + RESET_CANARY(cur);
9310 + nxt = BLOCKAT(cur->next);
9312 + if (((char *)cur) + cur->size == (char *) nxt) {
9313 + /* cur and nxt shared an edge, combine them */
9314 + cur->size += nxt->size;
9315 + cur->next = nxt->next;
9316 +#ifdef __APC_SMA_DEBUG__
9317 + CHECK_CANARY(nxt);
9318 + nxt->id = -1; /* assert this or set it ? */
9320 + RESET_CANARY(nxt);
9322 + header->nfoffset = 0; /* Reset the next fit search marker */
9328 +/* {{{ apc_sma_init */
9330 +void apc_sma_init(int numseg, int segsize, char *mmap_file_mask)
9334 + if (sma_initialized) {
9337 + sma_initialized = 1;
9341 + * I don't think multiple anonymous mmaps makes any sense
9342 + * so force sma_numseg to 1 in this case
9344 + if(!mmap_file_mask ||
9345 + (mmap_file_mask && !strlen(mmap_file_mask)) ||
9346 + (mmap_file_mask && !strcmp(mmap_file_mask, "/dev/zero"))) {
9349 + sma_numseg = numseg > 0 ? numseg : DEFAULT_NUMSEG;
9352 + sma_numseg = numseg > 0 ? numseg : DEFAULT_NUMSEG;
9355 + sma_segsize = segsize > 0 ? segsize : DEFAULT_SEGSIZE;
9357 + sma_segments = (int*) apc_emalloc(sma_numseg*sizeof(int));
9358 + sma_shmaddrs = (void**) apc_emalloc(sma_numseg*sizeof(void*));
9360 + for (i = 0; i < sma_numseg; i++) {
9366 + sma_segments[i] = sma_segsize;
9367 + sma_shmaddrs[i] = apc_mmap(mmap_file_mask, sma_segsize);
9368 + if(sma_numseg != 1) memcpy(&mmap_file_mask[strlen(mmap_file_mask)-6], "XXXXXX", 6);
9370 + sma_segments[i] = apc_shm_create(NULL, i, sma_segsize);
9371 + sma_shmaddrs[i] = apc_shm_attach(sma_segments[i]);
9373 + shmaddr = sma_shmaddrs[i];
9375 + header = (header_t*) shmaddr;
9376 + apc_lck_create(NULL, 0, 1, header->sma_lock);
9377 + header->segsize = sma_segsize;
9378 + header->avail = sma_segsize - sizeof(header_t) - sizeof(block_t) -
9379 + ALIGNWORD(sizeof(int));
9380 + header->nfoffset = 0;
9381 +#if ALLOC_DISTRIBUTION
9384 + for(j=0; j<30; j++) header->adist[j] = 0;
9387 + block = BLOCKAT(sizeof(header_t));
9389 + block->next = sizeof(header_t) + sizeof(block_t);
9390 + SET_CANARY(block);
9391 +#ifdef __APC_SMA_DEBUG__
9394 + block = BLOCKAT(block->next);
9395 + block->size = header->avail;
9397 + SET_CANARY(block);
9398 +#ifdef __APC_SMA_DEBUG__
9405 +/* {{{ apc_sma_cleanup */
9406 +void apc_sma_cleanup()
9410 + assert(sma_initialized);
9412 + for (i = 0; i < sma_numseg; i++) {
9413 + apc_lck_destroy(((header_t*)sma_shmaddrs[i])->sma_lock);
9415 + apc_unmap(sma_shmaddrs[i], sma_segments[i]);
9417 + apc_shm_detach(sma_shmaddrs[i]);
9420 + sma_initialized = 0;
9421 + apc_efree(sma_segments);
9422 + apc_efree(sma_shmaddrs);
9426 +/* {{{ apc_sma_malloc */
9427 +void* apc_sma_malloc(size_t n)
9433 + assert(sma_initialized);
9434 + LOCK(((header_t*)sma_shmaddrs[sma_lastseg])->sma_lock);
9436 + off = sma_allocate(sma_shmaddrs[sma_lastseg], n);
9438 + void* p = (void *)(((char *)(sma_shmaddrs[sma_lastseg])) + off);
9439 + if (APCG(mem_size_ptr) != NULL) { *(APCG(mem_size_ptr)) += n; }
9440 + UNLOCK(((header_t*)sma_shmaddrs[sma_lastseg])->sma_lock);
9443 + UNLOCK(((header_t*)sma_shmaddrs[sma_lastseg])->sma_lock);
9445 + for (i = 0; i < sma_numseg; i++) {
9446 + LOCK(((header_t*)sma_shmaddrs[i])->sma_lock);
9447 + if (i == sma_lastseg) {
9450 + off = sma_allocate(sma_shmaddrs[i], n);
9452 + void* p = (void *)(((char *)(sma_shmaddrs[i])) + off);
9453 + if (APCG(mem_size_ptr) != NULL) { *(APCG(mem_size_ptr)) += n; }
9454 + UNLOCK(((header_t*)sma_shmaddrs[i])->sma_lock);
9458 + UNLOCK(((header_t*)sma_shmaddrs[i])->sma_lock);
9465 +/* {{{ apc_sma_realloc */
9466 +void* apc_sma_realloc(void *p, size_t n)
9469 + return apc_sma_malloc(n);
9473 +/* {{{ apc_sma_strdup */
9474 +char* apc_sma_strdup(const char* s)
9479 + if(!s) return NULL;
9481 + len = strlen(s)+1;
9482 + q = apc_sma_malloc(len);
9483 + if(!q) return NULL;
9484 + memcpy(q, s, len);
9489 +/* {{{ apc_sma_free */
9490 +void apc_sma_free(void* p)
9501 + assert(sma_initialized);
9503 + for (i = 0; i < sma_numseg; i++) {
9504 + LOCK(((header_t*)sma_shmaddrs[i])->sma_lock);
9505 + offset = (size_t)((char *)p - (char *)(sma_shmaddrs[i]));
9506 + if (p >= sma_shmaddrs[i] && offset < sma_segsize) {
9507 + d_size = sma_deallocate(sma_shmaddrs[i], offset);
9508 + if (APCG(mem_size_ptr) != NULL) { *(APCG(mem_size_ptr)) -= d_size; }
9509 + UNLOCK(((header_t*)sma_shmaddrs[i])->sma_lock);
9512 + UNLOCK(((header_t*)sma_shmaddrs[i])->sma_lock);
9515 + apc_eprint("apc_sma_free: could not locate address %p", p);
9519 +/* {{{ apc_sma_info */
9520 +apc_sma_info_t* apc_sma_info(zend_bool limited)
9522 + apc_sma_info_t* info;
9523 + apc_sma_link_t** link;
9528 + if (!sma_initialized) {
9532 + info = (apc_sma_info_t*) apc_emalloc(sizeof(apc_sma_info_t));
9533 + info->num_seg = sma_numseg;
9534 + info->seg_size = sma_segsize - sizeof(header_t) - sizeof(block_t) - ALIGNWORD(sizeof(int));
9536 + info->list = apc_emalloc(info->num_seg * sizeof(apc_sma_link_t*));
9537 + for (i = 0; i < sma_numseg; i++) {
9538 + info->list[i] = NULL;
9541 + if(limited) return info;
9543 + /* For each segment */
9544 + for (i = 0; i < sma_numseg; i++) {
9545 + RDLOCK(((header_t*)sma_shmaddrs[i])->sma_lock);
9546 + shmaddr = sma_shmaddrs[i];
9547 + prv = BLOCKAT(sizeof(header_t));
9549 + link = &info->list[i];
9551 + /* For each block in this segment */
9552 + while (prv->next != 0) {
9553 + block_t* cur = BLOCKAT(prv->next);
9554 +#ifdef __APC_SMA_DEBUG__
9555 + CHECK_CANARY(cur);
9558 + *link = apc_emalloc(sizeof(apc_sma_link_t));
9559 + (*link)->size = cur->size;
9560 + (*link)->offset = prv->next;
9561 + (*link)->next = NULL;
9562 + link = &(*link)->next;
9566 + UNLOCK(((header_t*)sma_shmaddrs[i])->sma_lock);
9573 +/* {{{ apc_sma_free_info */
9574 +void apc_sma_free_info(apc_sma_info_t* info)
9578 + for (i = 0; i < info->num_seg; i++) {
9579 + apc_sma_link_t* p = info->list[i];
9581 + apc_sma_link_t* q = p;
9586 + apc_efree(info->list);
9591 +/* {{{ apc_sma_get_avail_mem */
9592 +int apc_sma_get_avail_mem()
9594 + int avail_mem = 0;
9597 + for (i = 0; i < sma_numseg; i++) {
9598 + header_t* header = (header_t*) sma_shmaddrs[i];
9599 + avail_mem += header->avail;
9605 +#if ALLOC_DISTRIBUTION
9606 +size_t *apc_sma_get_alloc_distribution(void) {
9607 + header_t* header = (header_t*) sma_shmaddrs[0];
9608 + return header->adist;
9613 +/* {{{ apc_sma_check_integrity */
9614 +void apc_sma_check_integrity()
9618 + /* For each segment */
9619 + for (i = 0; i < sma_numseg; i++) {
9620 + char* shmaddr = sma_shmaddrs[i];
9621 + header_t* header = (header_t*) shmaddr;
9622 + block_t* prv = BLOCKAT(sizeof(header_t));
9625 + /* For each block in this segment */
9626 + while (prv->next != 0) {
9627 + block_t* cur = BLOCKAT(prv->next);
9628 + avail += cur->size;
9632 + assert(avail == header->avail);
9639 + * Local variables:
9641 + * c-basic-offset: 4
9643 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
9644 + * vim<600: expandtab sw=4 ts=4 sts=4
9646 diff -ruN php-5.1.6.old/ext/apc/apc_sma.h php-5.1.6/ext/APC/apc_sma.h
9647 --- php-5.1.6.old/ext/apc/apc_sma.h 1969-12-31 18:00:00.000000000 -0600
9648 +++ php-5.1.6/ext/apc/apc_sma.h 2007-04-02 18:05:30.000000000 -0500
9651 + +----------------------------------------------------------------------+
9653 + +----------------------------------------------------------------------+
9654 + | Copyright (c) 2006 The PHP Group |
9655 + +----------------------------------------------------------------------+
9656 + | This source file is subject to version 3.01 of the PHP license, |
9657 + | that is bundled with this package in the file LICENSE, and is |
9658 + | available through the world-wide-web at the following url: |
9659 + | http://www.php.net/license/3_01.txt |
9660 + | If you did not receive a copy of the PHP license and are unable to |
9661 + | obtain it through the world-wide-web, please send a note to |
9662 + | license@php.net so we can mail you a copy immediately. |
9663 + +----------------------------------------------------------------------+
9664 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
9665 + +----------------------------------------------------------------------+
9667 + This software was contributed to PHP by Community Connect Inc. in 2002
9668 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
9669 + Future revisions and derivatives of this source code must acknowledge
9670 + Community Connect Inc. as the original contributor of this module by
9671 + leaving this note intact in the source code.
9673 + All other licensing and usage conditions are those of the PHP Group.
9677 +/* $Id: apc_sma.h,v 1.16 2007/02/24 11:59:40 rasmus Exp $ */
9682 +#define ALLOC_DISTRIBUTION 0
9686 +/* Simple shared memory allocator */
9688 +extern void apc_sma_init(int numseg, int segsize, char *mmap_file_mask);
9689 +extern void apc_sma_cleanup();
9690 +extern void* apc_sma_malloc(size_t size);
9691 +extern void* apc_sma_realloc(void* p, size_t size);
9692 +extern char* apc_sma_strdup(const char *s);
9693 +extern void apc_sma_free(void* p);
9694 +#if ALLOC_DISTRIBUTION
9695 +extern size_t *apc_sma_get_alloc_distribution();
9698 +/* {{{ struct definition: apc_sma_link_t */
9699 +typedef struct apc_sma_link_t apc_sma_link_t;
9700 +struct apc_sma_link_t {
9701 + int size; /* size of this free block */
9702 + int offset; /* offset in segment of this block */
9703 + apc_sma_link_t* next; /* link to next free block */
9707 +/* {{{ struct definition: apc_sma_info_t */
9708 +typedef struct apc_sma_info_t apc_sma_info_t;
9709 +struct apc_sma_info_t {
9710 + int num_seg; /* number of shared memory segments */
9711 + int seg_size; /* size of each shared memory segment */
9712 + apc_sma_link_t** list; /* there is one list per segment */
9716 +extern apc_sma_info_t* apc_sma_info(zend_bool limited);
9717 +extern void apc_sma_free_info(apc_sma_info_t* info);
9719 +extern int apc_sma_get_avail_mem();
9720 +extern void apc_sma_check_integrity();
9725 + * Local variables:
9727 + * c-basic-offset: 4
9729 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
9730 + * vim<600: expandtab sw=4 ts=4 sts=4
9732 diff -ruN php-5.1.6.old/ext/apc/apc_spin.c php-5.1.6/ext/APC/apc_spin.c
9733 --- php-5.1.6.old/ext/apc/apc_spin.c 1969-12-31 18:00:00.000000000 -0600
9734 +++ php-5.1.6/ext/apc/apc_spin.c 2007-04-02 18:05:30.000000000 -0500
9737 + +----------------------------------------------------------------------+
9739 + +----------------------------------------------------------------------+
9740 + | Copyright (c) 2007 The PHP Group |
9741 + +----------------------------------------------------------------------+
9742 + | This source file is subject to version 3.01 of the PHP license, |
9743 + | that is bundled with this package in the file LICENSE, and is |
9744 + | available through the world-wide-web at the following url: |
9745 + | http://www.php.net/license/3_01.txt |
9746 + | If you did not receive a copy of the PHP license and are unable to |
9747 + | obtain it through the world-wide-web, please send a note to |
9748 + | license@php.net so we can mail you a copy immediately. |
9749 + +----------------------------------------------------------------------+
9750 + | Authors: Brian Shire <shire@php.net> |
9751 + +----------------------------------------------------------------------+
9755 +/* $Id: apc_spin.c,v 3.1 2007/01/29 07:39:02 shire Exp $ */
9757 +#include "apc_spin.h"
9759 +#ifdef APC_SPIN_LOCKS
9761 +slock_t *apc_slock_create(slock_t *lock)
9763 + S_INIT_LOCK(lock);
9766 +void apc_slock_destroy(slock_t *lock)
9768 + S_LOCK_FREE(lock);
9771 +void apc_slock_lock(slock_t *lock)
9776 +void apc_slock_unlock(slock_t *lock)
9781 +zend_bool apc_slock_nonblocking_lock(slock_t *lock)
9783 + /* Technically we aren't supposed to call this directly, but the original
9784 + * code provides no method for absolute non-blocking locks, so we'll call into
9785 + * the TAS (test and set) functionality directly
9787 + return !(TAS(lock)); /* if TAS returns 0 we obtained the lock, otherwise we failed */
9794 + * Local variables:
9796 + * c-basic-offset: 4
9798 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
9799 + * vim<600: expandtab sw=4 ts=4 sts=4
9801 diff -ruN php-5.1.6.old/ext/apc/apc_spin.h php-5.1.6/ext/APC/apc_spin.h
9802 --- php-5.1.6.old/ext/apc/apc_spin.h 1969-12-31 18:00:00.000000000 -0600
9803 +++ php-5.1.6/ext/apc/apc_spin.h 2007-04-02 18:05:30.000000000 -0500
9806 + +----------------------------------------------------------------------+
9808 + +----------------------------------------------------------------------+
9809 + | Copyright (c) 2007 The PHP Group |
9810 + +----------------------------------------------------------------------+
9811 + | This source file is subject to version 3.01 of the PHP license, |
9812 + | that is bundled with this package in the file LICENSE, and is |
9813 + | available through the world-wide-web at the following url: |
9814 + | http://www.php.net/license/3_01.txt |
9815 + | If you did not receive a copy of the PHP license and are unable to |
9816 + | obtain it through the world-wide-web, please send a note to |
9817 + | license@php.net so we can mail you a copy immediately. |
9818 + +----------------------------------------------------------------------+
9819 + | Authors: Brian Shire <shire@php.net> |
9820 + +----------------------------------------------------------------------+
9824 +/* $Id: apc_spin.h,v 3.1 2007/01/29 07:39:02 shire Exp $ */
9831 +#ifdef APC_SPIN_LOCKS
9833 +#include "pgsql_s_lock.h"
9835 +pthread_mutex_t *apc_spin_create();
9836 +void apc_spin_destroy(pthread_mutex_t *lock);
9837 +void apc_spin_lock(pthread_mutex_t *lock);
9838 +void apc_spin_unlock(pthread_mutex_t *lock);
9839 +zend_bool apc_spin_nonblocking_lock(pthread_mutex_t *lock);
9846 + * Local variables:
9848 + * c-basic-offset: 4
9850 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
9851 + * vim<600: expandtab sw=4 ts=4 sts=4
9853 diff -ruN php-5.1.6.old/ext/apc/apc_stack.c php-5.1.6/ext/APC/apc_stack.c
9854 --- php-5.1.6.old/ext/apc/apc_stack.c 1969-12-31 18:00:00.000000000 -0600
9855 +++ php-5.1.6/ext/apc/apc_stack.c 2007-04-02 18:05:30.000000000 -0500
9858 + +----------------------------------------------------------------------+
9860 + +----------------------------------------------------------------------+
9861 + | Copyright (c) 2006 The PHP Group |
9862 + +----------------------------------------------------------------------+
9863 + | This source file is subject to version 3.01 of the PHP license, |
9864 + | that is bundled with this package in the file LICENSE, and is |
9865 + | available through the world-wide-web at the following url: |
9866 + | http://www.php.net/license/3_01.txt |
9867 + | If you did not receive a copy of the PHP license and are unable to |
9868 + | obtain it through the world-wide-web, please send a note to |
9869 + | license@php.net so we can mail you a copy immediately. |
9870 + +----------------------------------------------------------------------+
9871 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
9872 + +----------------------------------------------------------------------+
9874 + This software was contributed to PHP by Community Connect Inc. in 2002
9875 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
9876 + Future revisions and derivatives of this source code must acknowledge
9877 + Community Connect Inc. as the original contributor of this module by
9878 + leaving this note intact in the source code.
9880 + All other licensing and usage conditions are those of the PHP Group.
9884 +/* $Id: apc_stack.c,v 3.4 2006/03/12 00:31:45 rasmus Exp $ */
9886 +#include "apc_stack.h"
9889 +struct apc_stack_t {
9895 +apc_stack_t* apc_stack_create(int size_hint)
9897 + apc_stack_t* stack = (apc_stack_t*) apc_emalloc(sizeof(apc_stack_t));
9899 + stack->capacity = (size_hint > 0) ? size_hint : 10;
9901 + stack->data = (void**) apc_emalloc(sizeof(void*) * stack->capacity);
9906 +void apc_stack_destroy(apc_stack_t* stack)
9908 + if (stack != NULL) {
9909 + apc_efree(stack->data);
9914 +void apc_stack_clear(apc_stack_t* stack)
9916 + assert(stack != NULL);
9920 +void apc_stack_push(apc_stack_t* stack, void* item)
9922 + assert(stack != NULL);
9923 + if (stack->size == stack->capacity) {
9924 + stack->capacity *= 2;
9925 + stack->data = apc_erealloc(stack->data, sizeof(void*)*stack->capacity);
9927 + stack->data[stack->size++] = item;
9930 +void* apc_stack_pop(apc_stack_t* stack)
9932 + assert(stack != NULL && stack->size > 0);
9933 + return stack->data[--stack->size];
9936 +void* apc_stack_top(apc_stack_t* stack)
9938 + assert(stack != NULL && stack->size > 0);
9939 + return stack->data[stack->size-1];
9942 +void* apc_stack_get(apc_stack_t* stack, int n)
9944 + assert(stack != NULL && stack->size > n);
9945 + return stack->data[n];
9948 +int apc_stack_size(apc_stack_t* stack)
9950 + assert(stack != NULL);
9951 + return stack->size;
9955 + * Local variables:
9957 + * c-basic-offset: 4
9959 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
9960 + * vim<600: expandtab sw=4 ts=4 sts=4
9962 diff -ruN php-5.1.6.old/ext/apc/apc_stack.h php-5.1.6/ext/APC/apc_stack.h
9963 --- php-5.1.6.old/ext/apc/apc_stack.h 1969-12-31 18:00:00.000000000 -0600
9964 +++ php-5.1.6/ext/apc/apc_stack.h 2007-04-02 18:05:30.000000000 -0500
9967 + +----------------------------------------------------------------------+
9969 + +----------------------------------------------------------------------+
9970 + | Copyright (c) 2006 The PHP Group |
9971 + +----------------------------------------------------------------------+
9972 + | This source file is subject to version 3.01 of the PHP license, |
9973 + | that is bundled with this package in the file LICENSE, and is |
9974 + | available through the world-wide-web at the following url: |
9975 + | http://www.php.net/license/3_01.txt |
9976 + | If you did not receive a copy of the PHP license and are unable to |
9977 + | obtain it through the world-wide-web, please send a note to |
9978 + | license@php.net so we can mail you a copy immediately. |
9979 + +----------------------------------------------------------------------+
9980 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
9981 + | George Schlossnagle <george@omniti.com> |
9982 + +----------------------------------------------------------------------+
9984 + This software was contributed to PHP by Community Connect Inc. in 2002
9985 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
9986 + Future revisions and derivatives of this source code must acknowledge
9987 + Community Connect Inc. as the original contributor of this module by
9988 + leaving this note intact in the source code.
9990 + All other licensing and usage conditions are those of the PHP Group.
9994 +/* $Id: apc_stack.h,v 3.4 2006/03/12 00:31:45 rasmus Exp $ */
9996 +#ifndef APC_STACK_H
9997 +#define APC_STACK_H
9999 +/* Basic stack datatype */
10001 +#define T apc_stack_t*
10002 +typedef struct apc_stack_t apc_stack_t; /* opaque stack type */
10004 +extern T apc_stack_create(int size_hint);
10005 +extern void apc_stack_destroy(T stack);
10006 +extern void apc_stack_clear(T stack);
10007 +extern void apc_stack_push(T stack, void* item);
10008 +extern void* apc_stack_pop(T stack);
10009 +extern void* apc_stack_top(T stack);
10010 +extern void* apc_stack_get(T stack, int n);
10011 +extern int apc_stack_size(T stack);
10017 + * Local variables:
10019 + * c-basic-offset: 4
10021 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
10022 + * vim<600: expandtab sw=4 ts=4 sts=4
10024 diff -ruN php-5.1.6.old/ext/apc/apc_zend.c php-5.1.6/ext/APC/apc_zend.c
10025 --- php-5.1.6.old/ext/apc/apc_zend.c 1969-12-31 18:00:00.000000000 -0600
10026 +++ php-5.1.6/ext/apc/apc_zend.c 2007-04-02 18:05:30.000000000 -0500
10029 + +----------------------------------------------------------------------+
10031 + +----------------------------------------------------------------------+
10032 + | Copyright (c) 2006 The PHP Group |
10033 + +----------------------------------------------------------------------+
10034 + | This source file is subject to version 3.01 of the PHP license, |
10035 + | that is bundled with this package in the file LICENSE, and is |
10036 + | available through the world-wide-web at the following url: |
10037 + | http://www.php.net/license/3_01.txt |
10038 + | If you did not receive a copy of the PHP license and are unable to |
10039 + | obtain it through the world-wide-web, please send a note to |
10040 + | license@php.net so we can mail you a copy immediately. |
10041 + +----------------------------------------------------------------------+
10042 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
10043 + +----------------------------------------------------------------------+
10045 + This software was contributed to PHP by Community Connect Inc. in 2002
10046 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
10047 + Future revisions and derivatives of this source code must acknowledge
10048 + Community Connect Inc. as the original contributor of this module by
10049 + leaving this note intact in the source code.
10051 + All other licensing and usage conditions are those of the PHP Group.
10055 +/* $Id: apc_zend.c,v 3.14 2007/04/02 22:57:10 rasmus Exp $ */
10057 +#include "apc_zend.h"
10058 +#include "apc_globals.h"
10060 +void* apc_php_malloc(size_t n)
10062 + return emalloc(n);
10065 +void apc_php_free(void* p)
10070 +#ifndef ZEND_VM_KIND_CALL /* Not currently defined by any ZE version */
10071 +# define ZEND_VM_KIND_CALL 1
10074 +#ifndef ZEND_VM_KIND /* Indicates PHP < 5.1 */
10075 +# define ZEND_VM_KIND ZEND_VM_KIND_CALL
10078 +#if defined(ZEND_ENGINE_2) && (ZEND_VM_KIND == ZEND_VM_KIND_CALL)
10079 +# define APC_OPCODE_OVERRIDE
10082 +#ifdef APC_OPCODE_OVERRIDE
10084 +#ifdef ZEND_ENGINE_2_1
10085 +/* Taken from Zend/zend_vm_execute.h */
10086 +#define _CONST_CODE 0
10087 +#define _TMP_CODE 1
10088 +#define _VAR_CODE 2
10089 +#define _UNUSED_CODE 3
10090 +#define _CV_CODE 4
10091 +static inline int _apc_opcode_handler_decode(zend_op *opline)
10093 + static const int apc_vm_decode[] = {
10094 + _UNUSED_CODE, /* 0 */
10095 + _CONST_CODE, /* 1 = IS_CONST */
10096 + _TMP_CODE, /* 2 = IS_TMP_VAR */
10097 + _UNUSED_CODE, /* 3 */
10098 + _VAR_CODE, /* 4 = IS_VAR */
10099 + _UNUSED_CODE, /* 5 */
10100 + _UNUSED_CODE, /* 6 */
10101 + _UNUSED_CODE, /* 7 */
10102 + _UNUSED_CODE, /* 8 = IS_UNUSED */
10103 + _UNUSED_CODE, /* 9 */
10104 + _UNUSED_CODE, /* 10 */
10105 + _UNUSED_CODE, /* 11 */
10106 + _UNUSED_CODE, /* 12 */
10107 + _UNUSED_CODE, /* 13 */
10108 + _UNUSED_CODE, /* 14 */
10109 + _UNUSED_CODE, /* 15 */
10110 + _CV_CODE /* 16 = IS_CV */
10112 + return (opline->opcode * 25) + (apc_vm_decode[opline->op1.op_type] * 5) + apc_vm_decode[opline->op2.op_type];
10115 +# define APC_ZEND_OPLINE zend_op *opline = execute_data->opline;
10116 +# define APC_OPCODE_HANDLER_DECODE(opline) _apc_opcode_handler_decode(opline)
10117 +# if PHP_MAJOR_VERSION >= 6
10118 +# define APC_OPCODE_HANDLER_COUNT ((25 * 152) + 1)
10120 +# define APC_OPCODE_HANDLER_COUNT ((25 * 151) + 1)
10122 +# define APC_REPLACE_OPCODE(opname) { int i; for(i = 0; i < 25; i++) if (zend_opcode_handlers[(opname*25) + i]) zend_opcode_handlers[(opname*25) + i] = apc_op_##opname; }
10125 +# define APC_ZEND_ONLINE
10126 +# define APC_OPCODE_HANDLER_DECODE(opline) (opline->opcode)
10127 +# define APC_OPCODE_HANDLER_COUNT 512
10128 +# define APC_REPLACE_OPCODE(opname) zend_opcode_handlers[opname] = apc_op_##opname;
10131 +static opcode_handler_t *apc_original_opcode_handlers;
10132 +static opcode_handler_t apc_opcode_handlers[APC_OPCODE_HANDLER_COUNT];
10134 +#define APC_EX_T(offset) (*(temp_variable *)((char*)execute_data->Ts + offset))
10136 +static zval *apc_get_zval_ptr(znode *node, zval **freeval, zend_execute_data *execute_data TSRMLS_DC)
10140 + switch (node->op_type) {
10142 + return &(node->u.constant);
10144 + return APC_EX_T(node->u.var).var.ptr;
10146 + return (*freeval = &APC_EX_T(node->u.var).tmp_var);
10147 +#ifdef ZEND_ENGINE_2_1
10150 + zval ***ret = &execute_data->CVs[node->u.var];
10153 + zend_compiled_variable *cv = &EG(active_op_array)->vars[node->u.var];
10155 + if (zend_hash_quick_find(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value, (void**)ret)==FAILURE) {
10156 + apc_nprint("Undefined variable: %s", cv->name);
10157 + return &EG(uninitialized_zval);
10169 +static int apc_op_ZEND_INCLUDE_OR_EVAL(ZEND_OPCODE_HANDLER_ARGS)
10172 + zval *freeop1 = NULL;
10173 + zval *inc_filename = NULL, tmp_inc_filename;
10174 + char realpath[MAXPATHLEN];
10175 + php_stream_wrapper *wrapper;
10176 + char *path_for_open;
10178 + #ifdef ZEND_ENGINE_2
10179 + apc_opflags_t* flags = NULL;
10182 + if (Z_LVAL(opline->op2.u.constant) != ZEND_INCLUDE_ONCE &&
10183 + Z_LVAL(opline->op2.u.constant) != ZEND_REQUIRE_ONCE) {
10184 + return apc_original_opcode_handlers[APC_OPCODE_HANDLER_DECODE(opline)](ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
10187 + inc_filename = apc_get_zval_ptr(&opline->op1, &freeop1, execute_data TSRMLS_CC);
10188 + if (Z_TYPE_P(inc_filename) != IS_STRING) {
10189 + tmp_inc_filename = *inc_filename;
10190 + zval_copy_ctor(&tmp_inc_filename);
10191 + convert_to_string(&tmp_inc_filename);
10192 + inc_filename = &tmp_inc_filename;
10195 + wrapper = php_stream_locate_url_wrapper(Z_STRVAL_P(inc_filename), &path_for_open, 0 TSRMLS_CC);
10196 + if (wrapper != &php_plain_files_wrapper ||
10197 + !IS_ABSOLUTE_PATH(path_for_open, strlen(path_for_open)) ||
10198 + !expand_filepath(path_for_open, realpath TSRMLS_CC)) {
10199 + /* Fallback to original handler */
10200 + if (inc_filename == &tmp_inc_filename) {
10201 + zval_dtor(&tmp_inc_filename);
10203 + return apc_original_opcode_handlers[APC_OPCODE_HANDLER_DECODE(opline)](ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
10206 + if (zend_hash_exists(&EG(included_files), realpath, strlen(realpath) + 1)) {
10207 + if (!(opline->result.u.EA.type & EXT_TYPE_UNUSED)) {
10208 + ALLOC_INIT_ZVAL(APC_EX_T(opline->result.u.var).var.ptr);
10209 + ZVAL_TRUE(APC_EX_T(opline->result.u.var).var.ptr);
10211 + if (inc_filename == &tmp_inc_filename) {
10212 + zval_dtor(&tmp_inc_filename);
10215 + zval_dtor(freeop1);
10217 + execute_data->opline++;
10221 + if (inc_filename == &tmp_inc_filename) {
10222 + zval_dtor(&tmp_inc_filename);
10225 + if(APCG(reserved_offset) != -1) {
10226 + /* Insanity alert: look into apc_compile.c for why a void** is cast to a apc_opflags_t* */
10227 + flags = (apc_opflags_t*) & (execute_data->op_array->reserved[APCG(reserved_offset)]);
10230 +#ifdef ZEND_ENGINE_2
10231 + if(flags && flags->deep_copy == 1) {
10232 + /* Since the op array is a local copy, we can cheat our way through the file inclusion by temporarily
10233 + * changing the op to a plain require/include, calling its handler and finally restoring the opcode.
10235 + Z_LVAL(opline->op2.u.constant) = (Z_LVAL(opline->op2.u.constant) == ZEND_INCLUDE_ONCE) ? ZEND_INCLUDE : ZEND_REQUIRE;
10236 + ret = apc_original_opcode_handlers[APC_OPCODE_HANDLER_DECODE(opline)](ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
10237 + Z_LVAL(opline->op2.u.constant) = (Z_LVAL(opline->op2.u.constant) == ZEND_INCLUDE) ? ZEND_INCLUDE_ONCE : ZEND_REQUIRE_ONCE;
10240 + /* do nothing, have nothing, be nothing */
10243 + ret = apc_original_opcode_handlers[APC_OPCODE_HANDLER_DECODE(opline)](ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
10249 +void apc_zend_init(TSRMLS_D)
10251 + zend_extension dummy_ext;
10252 +#ifdef ZEND_ENGINE_2
10253 + APCG(reserved_offset) = zend_get_resource_handle(&dummy_ext);
10254 + assert(APCG(reserved_offset) == dummy_ext.resource_number);
10255 + assert(APCG(reserved_offset) != -1);
10256 + assert(sizeof(apc_opflags_t) <= sizeof(void*));
10258 + if (!APCG(include_once)) {
10259 + /* If we're not overriding the INCLUDE_OR_EVAL handler, then just skip this malarkey */
10263 + memcpy(apc_opcode_handlers, zend_opcode_handlers, sizeof(apc_opcode_handlers));
10265 + /* 5.0 exposes zend_opcode_handlers differently than 5.1 and later */
10266 +#ifdef ZEND_ENGINE_2_1
10267 + apc_original_opcode_handlers = zend_opcode_handlers;
10268 + zend_opcode_handlers = apc_opcode_handlers;
10270 + apc_original_opcode_handlers = apc_opcode_handlers;
10273 + APC_REPLACE_OPCODE(ZEND_INCLUDE_OR_EVAL);
10276 +void apc_zend_shutdown(TSRMLS_D)
10278 + if (!APCG(include_once)) {
10279 + /* Nothing changed, nothing to restore */
10283 +#ifdef ZEND_ENGINE_2_1
10284 + zend_opcode_handlers = apc_original_opcode_handlers;
10286 + memcpy(zend_opcode_handlers, apc_original_opcode_handlers, sizeof(apc_opcode_handlers));
10290 +#else /* Opcode Overrides unavailable */
10292 +void apc_zend_init(TSRMLS_D) { }
10293 +void apc_zend_shutdown(TSRMLS_D) { }
10295 +#endif /* APC_OPCODE_OVERRIDE */
10298 + * Local variables:
10300 + * c-basic-offset: 4
10302 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
10303 + * vim<600: expandtab sw=4 ts=4 sts=4
10305 diff -ruN php-5.1.6.old/ext/apc/apc_zend.h php-5.1.6/ext/APC/apc_zend.h
10306 --- php-5.1.6.old/ext/apc/apc_zend.h 1969-12-31 18:00:00.000000000 -0600
10307 +++ php-5.1.6/ext/apc/apc_zend.h 2007-04-02 18:05:30.000000000 -0500
10310 + +----------------------------------------------------------------------+
10312 + +----------------------------------------------------------------------+
10313 + | Copyright (c) 2006 The PHP Group |
10314 + +----------------------------------------------------------------------+
10315 + | This source file is subject to version 3.01 of the PHP license, |
10316 + | that is bundled with this package in the file LICENSE, and is |
10317 + | available through the world-wide-web at the following url: |
10318 + | http://www.php.net/license/3_01.txt |
10319 + | If you did not receive a copy of the PHP license and are unable to |
10320 + | obtain it through the world-wide-web, please send a note to |
10321 + | license@php.net so we can mail you a copy immediately. |
10322 + +----------------------------------------------------------------------+
10323 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
10324 + +----------------------------------------------------------------------+
10326 + This software was contributed to PHP by Community Connect Inc. in 2002
10327 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
10328 + Future revisions and derivatives of this source code must acknowledge
10329 + Community Connect Inc. as the original contributor of this module by
10330 + leaving this note intact in the source code.
10332 + All other licensing and usage conditions are those of the PHP Group.
10336 +/* $Id: apc_zend.h,v 3.8 2006/09/01 21:59:16 pollita Exp $ */
10338 +#ifndef APC_ZEND_H
10339 +#define APC_ZEND_H
10341 +/* Utilities for interfacing with the zend engine */
10344 +#include "apc_php.h"
10346 +extern void* apc_php_malloc(size_t n);
10347 +extern void apc_php_free(void* p);
10349 +extern void apc_zend_init(TSRMLS_D);
10350 +extern void apc_zend_shutdown(TSRMLS_D);
10355 + * Local variables:
10357 + * c-basic-offset: 4
10359 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
10360 + * vim<600: expandtab sw=4 ts=4 sts=4
10362 diff -ruN php-5.1.6.old/ext/apc/CHANGELOG php-5.1.6/ext/APC/CHANGELOG
10363 --- php-5.1.6.old/ext/apc/CHANGELOG 1969-12-31 18:00:00.000000000 -0600
10364 +++ php-5.1.6/ext/apc/CHANGELOG 2007-04-02 18:05:30.000000000 -0500
10366 +3.0.14: 2007-03-21
10367 +- Build fix (Shire)
10368 +- Don't hook the upload hook if APC is disabled (Rasmus)
10369 +- Local shadow cache support (Gopal)
10370 +- Avoid uneccessary loops over op_arrays for "known" auto-globals (Gopal)
10371 +- Fix apc_add() to overwrite timed out user entries (Rasmus)
10372 +- Fix double inclusion of files with conditional classes in php4 (Gopal)
10373 +- Allocator fixes to reduce fragmentation (Gopal)
10375 +3.0.13: 2007-02-24
10376 +- File upload progress (Rasmus)
10377 +- Pthread mutex and spin locks (Shire)
10378 +- Recursive zval support for apc_fetch/_store (Shire, Gopal)
10379 +- apc.stat_ctime flag for ctime checks (Rasmus)
10380 +- Multiple key fetches with apc_fetch (Shire)
10381 +- Canary checks for shm memory deallocation (Gopal)
10382 +- Add hooks for external optimizer (Shire)
10383 +- Obsolete and remove apc optimizer (Gopal)
10384 +- APC info changes - cache insert rate, hit and miss rates (Shire)
10385 +- Fix apc_load_constants (Gopal)
10386 +- Rewrite dump opcode code to use vld (Gopal)
10387 +- Use apc_[ewn]print functions for error reporting (Shire)
10388 +- Auto global fixes and refactoring (Gopal, Shire)
10389 +- Fix memory leaks in object serialization (Ilia)
10390 +- Memory cleanup code for destructor order (Gopal)
10391 +- Win32 build fixes (Ilia, Wez)
10392 +- ZTS and Php 4 build fixes (Bjori)
10393 +- Add apc_add() function (Rasmus)
10394 +- Add optional limited flag to apc_sma_info() (Rasmus)
10396 +3.0.12p2: 2006-09-05
10397 +- Package version up
10399 +3.0,12p1: 2006-09-05
10400 +- PHP4 build fixes
10402 +3.0.12: 2006-09-05
10403 +- PHP 5.2 compatibility (Gopal)
10404 +- TSRM fixes (Gopal)
10405 +- Add extra flags to op_array->reserved to improve op array
10406 + processing code (Gopal)
10407 +- Fix crashes in optimizer and cli mode (Ilia)
10408 +- Optimizer fixes for PHP5 (Ilia, Gopal)
10409 +- Allow multiple inclusions of a file with a dynamic class (Gopal)
10410 +- Php 4 function table and properties fixes (Gopal)
10411 +- Fix memory leaks in apc_cache_info (Gopal)
10413 +3.0.11: 2006-08-16
10414 +- Made --enable-apc-mmap the default compile option (for real this time)
10415 +- Add an optional flag to apc_cache_info() and some apc.php tweaks to make it
10416 + only fetch header information to make it useful when you have tens of
10417 + thousands of entries. (Brian Shire)
10418 +- 64-bit fixes (George)
10419 +- Don't mix Full Path and Inode keys (George)
10420 +- Override ZEND_INCLUDE_OR_EVAL opcode (when possible) to speed up use of
10421 + require_once() and include_once() statements. (Sara)
10422 +- Add a non-blocking write_lock for cache inserts. This is a better approach
10423 + to prevent cache slams and deprecates the slam_defense setting. (Rasmus)
10424 +- A bit of work on the optimizer. (Sara)
10425 +- Various memory issues resolved. (Gopal)
10427 +3.0.10: 2006-03-11
10428 +- Add apc.stat ini flag which defaults to 1. If set to 0, the main script and any fullpath
10429 + includes will not be stat'ed for any changes. You will have to restart the server if you
10430 + change anything. This mode increases performance quite a bit, especially if you have a
10433 +- Get rid of the lock safety net hack I added in 3.0.9. It seems to cause more problems
10434 + than it solves. I'll need to revisit locking and signal handling at some point soon.
10437 +- Eliminate rand() call when slam_defense is not set (Rasmus)
10438 +- Fix for __isset problem (Gopal)
10439 +- Rewrite allocator from a "best fit" to a "next fit" algorithm (Rasmus)
10440 +- Added a Cache Full counter so we have an idea how many times the segment has filled up causing an expunge (Rasmus)
10441 +- Report back the correct number of available bytes in the segment instead of the allocated bytes. (Rasmus)
10442 +- Add cache busy flag which is set when an expunge is underway (Rasmus)
10443 +- Add automatic serialization of objects in apc_store() (Marcus)
10444 +- 64-bit .ini flag fix (Rasmus)
10445 +- Static members fix (Gopal)
10446 +- sma_cleanup() mem leak fix (Rasmus)
10447 +- Fix for http://pecl.php.net/bugs/5311 (Rasmus)
10448 +- Fix autoglobals JIT bug (Gopal)
10449 +- Fix instance bug (Gopal)
10450 +- Add a lock cleanup safety net to request shutdown (Rasmus)
10451 +- Fix apc.slam_defense edge-case bug (Rasmus)
10452 +- User entry memory usage tracking support (Ilia)
10453 +- Allow keys used in apc_store/apc_fetch/apc_delete to be binary safe and prevent conflicts between keys that are found at the start of other keys. (Ilia)
10456 +Fix invalid free in globals destructor introduced in 3.0.7 (Rasmus)
10457 +Cache corruption fix in cache-full cleanup code (Gopal)
10460 +- Fix to apc.php to show final segment in frag chart. (Ilia)
10461 +- A couple of win32 fixes. (Frank)
10462 +- Add apc.enable_cli ini directive. (Rasmus)
10463 +- Add test cases. (Marcus)
10464 +- Fix apc_define_constants() bug - http://pecl.php.net/bugs/5084 (Rasmus)
10465 +- Simplify user cache handling by removing the user_cache_stack (Rasmus)
10466 +- Fix apc_fetch() memory corruption (Andrei,Rasmus)
10467 +- Added apc.max_file_size INI setting that allows exclusion of large files from being cached. Default file size limit, 1 megabyte. (Ilia)
10470 +- Added apc.php to package.xml file.
10471 +- Track per-entry memory usage. (Val)
10472 +- Various apc.php fixes and enhancements. (Ralf, Ilia, Rasmus)
10473 +- fcntl locking robustness fixes. (Rasmus)
10474 +- Shared read-locks where possible. (Rasmus)
10475 +- Added file_update_protection configuration parameter. (Rasmus)
10476 +- Windows ZTS fixes (Frank)
10479 +- Make it easier for sapis that only populate file_handle->filename to use APC. (Rasmus)
10480 +- Support extensions such as bcompiler that need to hook into compile_file. (Val)
10481 +- Ralf Becker's apcgui code has now become the default apc.php status page. (Ralf, Rasmus, Ilia)
10482 +- Segfault in cache cleanup code (Ilia, Rasmus)
10485 +- Add win32 support (Edin )
10486 +- Add --with-apxs switch to work around problem when loading APC into Apache binary compiled with LFS switches (Rasmus)
10487 +- A couple of other minor fixes
10490 +- Fix compile problem against PHP 5.0.x
10493 +- Better shm error message
10499 +- PHP 5.1 support (Arun, Gopal, Rasmus)
10500 +- Major Inheritance bug fix (Arun, Gopal)
10503 +- ground-up rewrite sharing none of the original source code (djc)
10506 +- merge mmap / shm code to be in one file, module supports both modes now [mpb 2001-05-15]
10507 +- added apc.mode config parameter [mpb 2001-05-15] NOTE: You'll have to add
10508 + this parameter to your php.ini file to activate apc shm or mmap caching
10509 +- generic source cleanup (missing includes, PATH_MAX usage etc) [mpb
10511 +- fixed: realpath return result checking in generate_key [mpb 2001-05-15]
10512 +- updated: gui updated (extras/apc_gui-1.0.2.tar.gz)
10513 +- experminental 'fast' cache-retrieval [djc 2001-05-20]
10514 +- fixed regex support [gws 2001-05-16]
10515 +- enhanced reader-writer lock support [rg 2001-05-07]
10518 +- fixed (?) memory alignment bug on 64 bit archiecures
10519 +- added many cache visibiliy functions
10520 +- added opional fcntl locks under shm version
10521 +- numerous bug fixes
10524 +- added ability to detect and decompile compiled files placed as 'source'
10525 + [gws,dw 2001-01-30]
10526 +- fixed apc_rstat bug [gws 2001-01-29]
10527 +- added hack to support included urls [gws 2001-01-30]
10528 +- fixed apc_cache_index [mb 2001-01-31]
10529 +- added multiple regex support [gs 2001-02-03]
10530 +- added apc_cache_info [mb,gs 2001-02-03]
10533 +- partially fixed for Solaris [gws 2001-01-29]
10534 +- fixed mtime support for relative includes [gws 2001-01-29]
10535 +- code cleanup [yg,ta,gws 2001-01-29]
10538 +- support for mtime in mmap [yg,gws 2001-01-27]
10539 +- fixed indexed-array initialization bug [djc,gws 2001-01-27]
10542 +- support for relative include paths [djc,gws 2001-01-19]
10543 +- class member array support fixed [djc 2001-01-18]
10544 +- added apc_cache_index [gws 2001-01-18]
10547 +- support for class hierarchies greater than two levels deep [djc 2001-01-17]
10550 +- fixed support for class inheritance [djc 2001-01-16]
10553 +- support for inherited classes [gws 2001-01-15]
10554 +- support for intialization of class variables and objects [gws 2001-01-13]
10557 +- added optional file modification time check [djc 2001-01-12]
10558 diff -ruN php-5.1.6.old/ext/apc/config.m4 php-5.1.6/ext/APC/config.m4
10559 --- php-5.1.6.old/ext/apc/config.m4 1969-12-31 18:00:00.000000000 -0600
10560 +++ php-5.1.6/ext/apc/config.m4 2007-04-02 18:05:30.000000000 -0500
10563 +dnl $Id: config.m4,v 3.25 2007/02/24 15:57:59 rasmus Exp $
10566 +AC_MSG_CHECKING(whether apc needs to get compiler flags from apxs)
10568 +[ --with-apxs[=FILE] Get compiler flags from apxs -q. Provide the
10569 + pathname to the Apache apxs tool; defaults to "apxs".],[
10570 + if test "$withval" != "no"; then
10571 + if test "$withval" = "yes"; then
10573 + $APXS -q CFLAGS >/dev/null 2>&1
10574 + if test "$?" != "0" && test -x /usr/sbin/apxs; then #SUSE 6.x
10575 + APXS=/usr/sbin/apxs
10576 + elif test -x /usr/bin/apxs2; then
10577 + APXS=/usr/bin/apxs2
10578 + elif test -x /usr/sbin/apxs2; then
10579 + APXS=/usr/sbin/apxs2
10582 + PHP_EXPAND_PATH($withval, APXS)
10585 + $APXS -q CFLAGS >/dev/null 2>&1
10586 + if test "$?" != "0"; then
10589 + AC_MSG_RESULT([Sorry, I was not able to successfully run APXS. Possible reasons:])
10591 + AC_MSG_RESULT([1. Perl is not installed;])
10592 + AC_MSG_RESULT([2. Apache was not compiled with DSO support (--enable-module=so);])
10593 + AC_MSG_RESULT([3. 'apxs' is not in your path. Try to use --with-apxs=/path/to/apxs])
10594 + AC_MSG_RESULT([The output of $APXS follows])
10596 + AC_MSG_ERROR([Aborting])
10599 + APC_CFLAGS=`$APXS -q CFLAGS`
10600 + AC_MSG_RESULT(yes)
10602 + AC_MSG_RESULT(no)
10605 + AC_MSG_RESULT(no)
10608 +PHP_ARG_ENABLE(apc, whether to enable APC support,
10609 +[ --enable-apc Enable APC support])
10611 +AC_MSG_CHECKING(Checking whether we should use mmap)
10612 +AC_ARG_ENABLE(apc-mmap,
10613 +[ --disable-apc-mmap
10614 + Disable mmap support and use IPC shm instead],
10616 + PHP_APC_MMAP=$enableval
10617 + AC_MSG_RESULT($enableval)
10620 + AC_MSG_RESULT(yes)
10623 +AC_MSG_CHECKING(Checking whether we should use semaphore locking instead of fcntl)
10624 +AC_ARG_ENABLE(apc-sem,
10625 +[ --enable-apc-sem
10626 + Enable semaphore locks instead of fcntl],
10628 + PHP_APC_SEM=$enableval
10629 + AC_MSG_RESULT($enableval)
10632 + AC_MSG_RESULT(no)
10635 +AC_MSG_CHECKING(Checking whether we should use futex locking)
10636 +AC_ARG_ENABLE(apc-futex,
10637 +[ --enable-apc-futex
10638 + Enable linux futex based locks EXPERIMENTAL ],
10640 + PHP_APC_FUTEX=$enableval
10641 + AC_MSG_RESULT($enableval)
10645 + AC_MSG_RESULT(no)
10648 +if test "$PHP_APC_FUTEX" != "no"; then
10649 + AC_CHECK_HEADER(linux/futex.h, , [ AC_MSG_ERROR([futex.h not found. Please verify you that are running a 2.5 or older linux kernel and that futex support is enabled.]); ] )
10652 +AC_MSG_CHECKING(Checking whether we should use pthread mutex locking)
10653 +AC_ARG_ENABLE(apc-pthreadmutex,
10654 +[ --enable-apc-pthreadmutex
10655 + Enable pthread mutex locking EXPERIMENTAL ],
10657 + PHP_APC_PTHREADMUTEX=$enableval
10658 + AC_MSG_RESULT($enableval)
10661 + PHP_APC_PTHREADMUTEX=no
10662 + AC_MSG_RESULT(no)
10664 +if test "$PHP_APC_PTHREADMUTEX" != "no"; then
10665 + orig_LIBS="$LIBS"
10666 + LIBS="$LIBS -lpthread"
10669 + #include <sys/types.h>
10670 + #include <pthread.h>
10672 + pthread_mutex_t mutex;
10673 + pthread_mutexattr_t attr;
10675 + if(pthread_mutexattr_init(&attr)) {
10676 + puts("Unable to initialize pthread attributes (pthread_mutexattr_init).");
10679 + if(pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED)) {
10680 + puts("Unable to set PTHREAD_PROCESS_SHARED (pthread_mutexattr_setpshared), your system may not support shared mutex's which are required. (if you're using threads you should just use the built-in php thread locking).");
10683 + if(pthread_mutex_init(&mutex, &attr)) {
10684 + puts("Unable to initialize the mutex (pthread_mutex_init).");
10687 + if(pthread_mutexattr_destroy(&attr)) {
10688 + puts("Unable to destroy mutex attributes (pthread_mutexattr_destroy).");
10691 + if(pthread_mutex_destroy(&mutex)) {
10692 + puts("Unable to destroy mutex (pthread_mutex_destroy).");
10696 + puts("pthread mutex's are supported!");
10701 + PHP_ADD_LIBRARY(pthread)
10704 + AC_MSG_ERROR([It doesn't appear that pthread mutex's are supported on your system, please try a different configuration])
10707 + PHP_ADD_LIBRARY(pthread)
10710 + LIBS="$orig_LIBS"
10713 +AC_MSG_CHECKING(Checking whether we should use spin locks)
10714 +AC_ARG_ENABLE(apc-spinlocks,
10715 +[ --enable-apc-spinlocks
10716 + Enable spin locks EXPERIMENTAL ],
10718 + PHP_APC_SPINLOCKS=$enableval
10719 + AC_MSG_RESULT($enableval)
10722 + PHP_APC_SPINLOCKS=no
10723 + AC_MSG_RESULT(no)
10726 +if test "$PHP_APC" != "no"; then
10727 + test "$PHP_APC_MMAP" != "no" && AC_DEFINE(APC_MMAP, 1, [ ])
10728 + test "$PHP_APC_SEM" != "no" && AC_DEFINE(APC_SEM_LOCKS, 1, [ ])
10729 + test "$PHP_APC_FUTEX" != "no" && AC_DEFINE(APC_FUTEX_LOCKS, 1, [ ])
10730 + test "$PHP_APC_PTHREADMUTEX" != "no" && AC_DEFINE(APC_PTHREADMUTEX_LOCKS, 1, [ ])
10731 + test "$PHP_APC_SPINLOCKS" != "no" && AC_DEFINE(APC_SPIN_LOCKS, 1, [ ])
10733 + AC_CACHE_CHECK(for union semun, php_cv_semun,
10736 +#include <sys/types.h>
10737 +#include <sys/ipc.h>
10738 +#include <sys/sem.h>
10739 + ], [union semun x;], [
10745 + if test "$php_cv_semun" = "yes"; then
10746 + AC_DEFINE(HAVE_SEMUN, 1, [ ])
10748 + AC_DEFINE(HAVE_SEMUN, 0, [ ])
10751 + apc_sources="apc.c php_apc.c \
10761 + apc_pthreadmutex.c \
10769 + PHP_CHECK_LIBRARY(rt, shm_open, [PHP_ADD_LIBRARY(rt,,APC_SHARED_LIBADD)])
10770 + PHP_NEW_EXTENSION(apc, $apc_sources, $ext_shared,, \\$(APC_CFLAGS))
10771 + PHP_SUBST(APC_SHARED_LIBADD)
10772 + PHP_SUBST(APC_CFLAGS)
10773 + AC_DEFINE(HAVE_APC, 1, [ ])
10776 diff -ruN php-5.1.6.old/ext/apc/INSTALL php-5.1.6/ext/APC/INSTALL
10777 --- php-5.1.6.old/ext/apc/INSTALL 1969-12-31 18:00:00.000000000 -0600
10778 +++ php-5.1.6/ext/apc/INSTALL 2007-04-02 18:05:30.000000000 -0500
10780 +Installation Instructions for APC
10781 +---------------------------------
10783 +This version of APC should work on PHP 4.3.0 - 4.4.x and
10784 +5.1.0 - 5.2.x. Yes, that means PHP 5.0.x is no longer
10785 +supported. Upgrade to PHP 5.1.x or 5.2.x and you will
10786 +notice all sorts of performance increases.
10790 +Building from CVS can be done like this:
10792 + cvs -d :pserver:cvsread@cvs.php.net:/repository login
10794 + cvs -d :pserver:cvsread@cvs.php.net:/repository co pecl/apc
10797 + ./configure --enable-apc-mmap --with-apxs --with-php-config=/usr/local/php/bin/php-config
10801 +Suggested Configuration (in your php.ini file)
10802 +----------------------------------------------
10805 + apc.shm_segments=1
10808 + apc.user_ttl=7200
10809 + apc.num_files_hint=1024
10810 + apc.mmap_file_mask=/tmp/apc.XXXXXX
10813 +These are fully described at the bottom of this file.
10815 +PHP 4 Optimization
10816 +------------------
10817 +If you are trying to get every little bit of speed out of PHP4+APC, you need
10818 +to tell APC where to find your httpd.h file and also add -DAPC_PHP4_STAT to
10819 +your CPPFLAGS. (if you don't have httpd.h, install the apache_dev package
10820 +for your OS) and do:
10821 + export CPPFLAGS="-I/usr/include/apache-1.3 -DAPC_PHP4_STAT" (for bash on Debian)
10822 + setenv CPPFLAGS "-I/usr/include/apache-1.3 -DAPC_PHP4_STAT" (for tsch on Debian)
10823 +and then re-run your configure script.
10825 +This optimization saves a stat syscall on the main script file. In PHP5 this
10826 +optimization is automatic and doesn't need any special build flags.
10828 +The second thing you are going to want to do to save another syscall is to
10829 +compile using the --with-apxs configure switch. This should work for both
10830 +Apache1 and Apache2. Point it directly at your apxs2 script for Apache2.
10831 +eg. --with-apxs=/usr/local/bin/apxs2
10833 ++---------------------+
10834 +| QUICK INSTALL (DSO) |
10835 ++---------------------+
10837 +These instructions assume your PHP installation is located in /usr/local/php and you
10838 +want Apache optimizations (--with-apxs).
10840 +$ gunzip -c apc_x.y.tar.gz | tar xf -
10842 +$ /usr/local/php/bin/phpize
10843 +$ ./configure --enable-apc --enable-apc-mmap --with-apxs --with-php-config=/usr/local/php/bin/php-config
10847 +You will probably need to run the final command (make install) as root.
10849 +The above sequence of commands will install a .so file in your PHP
10850 +installation extension directory. The output of make install should display
10851 +that path to the screen.
10853 +Next you must edit your php.ini file, which is normally located in
10854 +/usr/local/php/lib/php.ini, and add the following line:
10856 + extension="apc.so"
10858 +Replace "/path/to/php/extensions" with whatever path was displayed when you
10859 +ran make install above.
10861 +Then restart your web server and consult the output of phpinfo(). If there is
10862 +an informational section for APC, the installation was successful.
10864 ++------------------------+
10865 +| QUICK INSTALL (Static) |
10866 ++------------------------+
10868 +APC will not successfully compile on all systems as a DSO. If you run into
10869 +problems using the DSO quick install, you can try to compile it statically
10870 +into PHP. (The DSO install is recommended, though.)
10872 +These instructions assume the current directory is the root of the PHP source
10873 +tree, and that you have already configured PHP by running its bundled
10877 +$ gunzip -c apc_x.y.tar.gz | tar xf -
10884 +Once this is complete, simply restart your web server. You do not need to
10885 +modify your php.ini file to enable APC.
10887 ++-----------------+
10888 +| VERBOSE INSTALL |
10889 ++-----------------+
10891 +These instructions assume your PHP installation is located in /usr/local/php.
10893 +1. Unpack your distribution file.
10895 + You will have downloaded a file named something like apc_x.y.tar.gz.
10896 + Unzip this file with a command like
10898 + gunzip apc_x.y.tar.gz
10900 + Next you have to untar it with
10902 + tar xvf apc_x.y.tar
10904 + This will create an apc_x.y directory. cd into this new directory:
10910 + phpize is a script that should have been installed with PHP, and is
10911 + normally located in /usr/local/php/bin assuming you installed PHP in
10912 + /usr/local/php. (If you do not have the phpize script, you must reinstall
10913 + PHP and be sure not to disable PEAR.)
10915 + Run the phpize command:
10917 + /usr/local/php/bin/phpize
10919 + Its output should resemble this:
10921 + autoheader: `config.h.in' is created
10922 + You should update your `aclocal.m4' by running aclocal.
10924 + PHP Api Version: 20020918
10925 + Zend Module Api No: 20020429
10926 + Zend Extension Api No: 20021010
10928 + phpize should create a configure script in the current directory. If you
10929 + get errors instead, you might be missing some required development tools,
10930 + such as autoconf or libtool. You can try downloading the latest versions
10931 + of those tools and running phpize again.
10933 +3. Run the configure script.
10935 + phpize creates a configure script. The only option you need to specify is
10936 + the location of your php-config script:
10938 + ./configure --enable-apc
10940 + php-config should be located in the same directory as phpize.
10942 + If you prefer to use mmap instead of the default IPC shared memory support,
10943 + add --enable-apc-mmap to your configure line.
10945 + If you prefer to use sysv IPC semaphores over the safer fcntl() locks, add
10946 + --enable-sem to your configure line. If you don't have a problem
10947 + with your server segaulting, or any other unnatural accumulation of
10948 + semaphores on your system, the semaphore based locking is slightly faster.
10950 +4. Compile and install the files. Simply type: make install
10952 + (You may need to be root in order to install)
10954 + If you encounter errors from libtool or gcc during this step, please
10955 + contact the project maintainer (dcowgill@php.net).
10957 +5. Edit your php.ini
10959 + make install should have printed a line resembling the following:
10961 + Installing shared extensions: /path/to/extension/
10963 + Copy the path /path/to/extension/ and add the following line to your
10964 + php.ini file (normally located in /usr/local/php/lib/php.ini):
10966 + extension="apc.so"
10968 + If you don't have a php.ini file in that location, you can create it now.
10970 +6. Restart the web server and test the installation.
10972 + Restart your web server now (for apache, it's apachectl restart) and
10973 + create a small test PHP file in your document root. The file should
10974 + contain just the following line:
10976 + <?php phpinfo() ?>
10978 + Request that file in a web browser. If there is an entry for APC in the
10979 + list of installed modules, the installation was successful.
10981 + If APC is not listed, consult your web server error log. If it contains an
10982 + error message saying that it can't load the APC extension, your system
10983 + might not be able to load shared libraries created with PHP's build
10984 + system. One alternative would be to compile APC statically into PHP. See
10985 + the Quick Install (Static) instructions above.
10987 + You should consult your error log anyway to see if APC generated any
10988 + errors. On BSD-based platforms, it is typical for APC to be unable to
10989 + allocate the default-sized shared memory segment. See below for hints on
10990 + raising your system's shared memory limitations.
10992 ++-----------------+
10993 +| CONFIGURING APC |
10994 ++-----------------+
10996 +Although the default APC settings are fine for many installations, serious
10997 +users should consider tuning the following parameters:
10999 + OPTION DESCRIPTION
11000 + ------------------ --------------------------------------------------
11001 + apc.enabled This can be set to 0 to disable APC. This is
11002 + primarily useful when APC is statically compiled
11003 + into PHP, since there is no other way to disable
11004 + it (when compiled as a DSO, the zend_extension
11005 + line can just be commented-out).
11008 + apc.shm_segments The number of shared memory segments to allocate
11009 + for the compiler cache. If APC is running out of
11010 + shared memory but you have already set
11011 + apc.shm_size as high as your system allows, you
11012 + can try raising this value. Setting this to a
11013 + value other than 1 has no effect in mmap mode
11014 + since mmap'ed shm segments don't have size limits.
11017 + apc.shm_size The size of each shared memory segment in MB.
11018 + By default, some systems (including most BSD
11019 + variants) have very low limits on the size of a
11020 + shared memory segment.
11023 + apc.optimization This option has been deprecated.
11026 + apc.num_files_hint A "hint" about the number of distinct source files
11027 + that will be included or requested on your web
11028 + server. Set to zero or omit if you're not sure;
11029 + this setting is mainly useful for sites that have
11030 + many thousands of source files.
11033 + apc.user_entries_hint Just like num_files_hint, a "hint" about the number
11034 + of distinct user cache variables to store.
11035 + Set to zero or omit if you're not sure;
11038 + apc.ttl The number of seconds a cache entry is allowed to
11039 + idle in a slot in case this cache entry slot is
11040 + needed by another entry. Leaving this at zero
11041 + means that your cache could potentially fill up
11042 + with stale entries while newer entries won't be
11046 + apc.user_ttl The number of seconds a user cache entry is allowed
11047 + to idle in a slot in case this cache entry slot is
11048 + needed by another entry. Leaving this at zero
11049 + means that your cache could potentially fill up
11050 + with stale entries while newer entries won't be
11055 + apc.gc_ttl The number of seconds that a cache entry may
11056 + remain on the garbage-collection list. This value
11057 + provides a failsafe in the event that a server
11058 + process dies while executing a cached source file;
11059 + if that source file is modified, the memory
11060 + allocated for the old version will not be
11061 + reclaimed until this TTL reached. Set to zero to
11062 + disable this feature.
11065 + apc.cache_by_default On by default, but can be set to off and used in
11066 + conjunction with positive apc.filters so that files
11067 + are only cached if matched by a positive filter.
11070 + apc.filters A comma-separated list of POSIX extended regular
11071 + expressions. If any pattern matches the source
11072 + filename, the file will not be cached. Note that
11073 + the filename used for matching is the one passed
11074 + to include/require, not the absolute path. If the
11075 + first character of the expression is a + then the
11076 + expression will be additive in the sense that any
11077 + files matched by the expression will be cached, and
11078 + if the first character is a - then anything matched
11079 + will not be cached. The - case is the default, so
11080 + it can be left off.
11083 + apc.mmap_file_mask If compiled with MMAP support by using --enable-mmap
11084 + this is the mktemp-style file_mask to pass to the
11085 + mmap module for determing whether your mmap'ed memory
11086 + region is going to be file-backed or shared memory
11087 + backed. For straight file-backed mmap, set it to
11088 + something like /tmp/apc.XXXXXX (exactly 6 X's).
11089 + To use POSIX-style shm_open/mmap put a ".shm"
11090 + somewhere in your mask. eg. "/apc.shm.XXXXXX"
11091 + You can also set it to "/dev/zero" to use your
11092 + kernel's /dev/zero interface to anonymous mmap'ed
11093 + memory. Leaving it undefined will force an
11097 + apc.slam_defense ** DEPRECATED - Use apc.write_lock instead **
11098 + On very busy servers whenever you start the server or
11099 + modify files you can create a race of many processes
11100 + all trying to cache the same file at the same time.
11101 + This option sets the percentage of processes that will
11102 + skip trying to cache an uncached file. Or think of it
11103 + as the probability of a single process to skip caching.
11104 + For example, setting this to 75 would mean that there is
11105 + a 75% chance that the process will not cache an uncached
11106 + file. So the higher the setting the greater the defense
11107 + against cache slams. Setting this to 0 disables this
11111 + apc.file_update_protection
11112 + When you modify a file on a live web server you really
11113 + should do so in an atomic manner. That is, write to a
11114 + temporary file and rename (mv) the file into its permanent
11115 + position when it is ready. Many text editors, cp, tar and
11116 + other such programs don't do this. This means that there
11117 + is a chance that a file is accessed (and cached) while it
11118 + is still being written to. This file_update_protection
11119 + setting puts a delay on caching brand new files. The
11120 + default is 2 seconds which means that if the modification
11121 + timestamp (mtime) on a file shows that it is less than 2
11122 + seconds old when it is accessed, it will not be cached.
11123 + The unfortunate person who accessed this half-written file
11124 + will still see weirdness, but at least it won't persist.
11125 + If you are certain you always atomically update your files
11126 + by using something like rsync which does this correctly, you
11127 + can turn this protection off by setting it to 0. If you
11128 + have a system that is flooded with io causing some update
11129 + procedure to take longer than 2 seconds, you may want to
11130 + increase this a bit.
11133 + apc.enable_cli Mostly for testing and debugging. Setting this enables APC
11134 + for the CLI version of PHP. Normally you wouldn't want to
11135 + create, populate and tear down the APC cache on every CLI
11136 + request, but for various test scenarios it is handy to be
11137 + able to enable APC for the CLI version of APC easily.
11140 + apc.max_file_size Prevents large files from being cached.
11143 + apc.stat Whether to stat the main script file and the fullpath
11144 + includes. If you turn this off you will need to restart
11145 + your server in order to update scripts.
11148 + apc.write_lock On busy servers when you first start up the server, or when
11149 + many files are modified, you can end up with all your processes
11150 + trying to compile and cache the same files. With write_lock
11151 + enabled, only one process at a time will try to compile an
11152 + uncached script while the other processes will run uncached
11153 + instead of sitting around waiting on a lock.
11156 + apc.report_autofilter Logs any scripts that were automatically excluded from being
11157 + cached due to early/late binding issues.
11160 + apc.rfc1867 RFC1867 File Upload Progress hook handler is only available
11161 + if you compiled APC against PHP 5.2.0 or later. When enabled
11162 + any file uploads which includes a field called
11163 + APC_UPLOAD_PROGRESS before the file field in an upload form
11164 + will cause APC to automatically create an upload_<key>
11165 + user cache entry where <key> is the value of the
11166 + APC_UPLOAD_PROGRESS form entry.
11168 + Note that the file upload tracking is not threadsafe at this
11169 + point, so new uploads that happen while a previous one is
11170 + still going will disable the tracking for the previous.
11173 + apc.localcache This enables a lock-free local process shadow-cache which
11174 + reduces lock contention when the cache is being written to.
11177 + apc.localcache.size The size of the local process shadow-cache, should be set to
11178 + a sufficently large value, approximately half of num_files_hint.
11181 + apc.include_once_override
11182 + Optimize include_once and require_once calls and avoid the
11183 + expensive system calls used.
11185 diff -ruN php-5.1.6.old/ext/apc/LICENSE php-5.1.6/ext/APC/LICENSE
11186 --- php-5.1.6.old/ext/apc/LICENSE 1969-12-31 18:00:00.000000000 -0600
11187 +++ php-5.1.6/ext/apc/LICENSE 2007-04-02 18:05:30.000000000 -0500
11189 +--------------------------------------------------------------------
11190 + The PHP License, version 3.01
11191 +Copyright (c) 1999 - 2006 The PHP Group. All rights reserved.
11192 +--------------------------------------------------------------------
11194 +Redistribution and use in source and binary forms, with or without
11195 +modification, is permitted provided that the following conditions
11198 + 1. Redistributions of source code must retain the above copyright
11199 + notice, this list of conditions and the following disclaimer.
11201 + 2. Redistributions in binary form must reproduce the above copyright
11202 + notice, this list of conditions and the following disclaimer in
11203 + the documentation and/or other materials provided with the
11206 + 3. The name "PHP" must not be used to endorse or promote products
11207 + derived from this software without prior written permission. For
11208 + written permission, please contact group@php.net.
11210 + 4. Products derived from this software may not be called "PHP", nor
11211 + may "PHP" appear in their name, without prior written permission
11212 + from group@php.net. You may indicate that your software works in
11213 + conjunction with PHP by saying "Foo for PHP" instead of calling
11214 + it "PHP Foo" or "phpfoo"
11216 + 5. The PHP Group may publish revised and/or new versions of the
11217 + license from time to time. Each version will be given a
11218 + distinguishing version number.
11219 + Once covered code has been published under a particular version
11220 + of the license, you may always continue to use it under the terms
11221 + of that version. You may also choose to use such covered code
11222 + under the terms of any subsequent version of the license
11223 + published by the PHP Group. No one other than the PHP Group has
11224 + the right to modify the terms applicable to covered code created
11225 + under this License.
11227 + 6. Redistributions of any form whatsoever must retain the following
11229 + "This product includes PHP software, freely available from
11230 + <http://www.php.net/software/>".
11232 +THIS SOFTWARE IS PROVIDED BY THE PHP DEVELOPMENT TEAM ``AS IS'' AND
11233 +ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
11234 +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
11235 +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PHP
11236 +DEVELOPMENT TEAM OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
11237 +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
11238 +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
11239 +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
11240 +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
11241 +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
11242 +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
11243 +OF THE POSSIBILITY OF SUCH DAMAGE.
11245 +--------------------------------------------------------------------
11247 +This software consists of voluntary contributions made by many
11248 +individuals on behalf of the PHP Group.
11250 +The PHP Group can be contacted via Email at group@php.net.
11252 +For more information on the PHP Group and the PHP project,
11253 +please see <http://www.php.net>.
11255 +PHP includes the Zend Engine, freely available at
11256 +<http://www.zend.com>.
11257 diff -ruN php-5.1.6.old/ext/apc/NOTICE php-5.1.6/ext/APC/NOTICE
11258 --- php-5.1.6.old/ext/apc/NOTICE 1969-12-31 18:00:00.000000000 -0600
11259 +++ php-5.1.6/ext/apc/NOTICE 2007-04-02 18:05:30.000000000 -0500
11261 +This is the NOTICE file that holds acknowledgements and stuff.
11263 +The Alternative PHP Cache (APC) is a free and open opcode cache for PHP.
11264 +This extension is being released under the PHP License for complete compliance
11265 +with PHP and to encourage wide-spread use. It is our intention that this
11266 +project be kept open source and that all commercial spin-offs contribute their
11267 +modifications back into the public source-tree.
11271 + George Schlossnagle
11273 +PHP5 support and major features by:
11275 + Gopal Vijayaraghavan
11278 +This software was contributed to PHP by Community Connect Inc. in 2002
11279 +and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
11280 +Future revisions and derivatives of this source code must acknowledge
11281 +Community Connect Inc. as the original contributor of this module by
11282 +leaving this note intact in the source code.
11284 +All other licensing and usage conditions are those of the PHP Group.
11286 +We would like to thank Community Connect Inc. and Yahoo! Inc. for supporting
11287 +this project and providing a challenging and stimulating environment in
11288 +which exciting projects can happen.
11291 + Mike Bretz bug fixes, GUI, and lots of work
11292 + Ricardo Galli changed read-write locks to prefer readers
11293 + Yann Grossel bug fixes
11294 + Thies Arntzen bug fixes
11295 + Sara Golemon optimizer work
11298 + Florian Baumert help debugging phplib problems
11299 + Thomas Duffey help debugging inheritance issues
11300 + Vibol Hou help debugging phplib problems
11301 + Angel Li diffs for ANSI comment compliance
11302 + Christian Rishøj help debugging phplib problems
11303 + Sascha Schumann memory error bug fix
11304 diff -ruN php-5.1.6.old/ext/apc/pgsql_s_lock.c php-5.1.6/ext/APC/pgsql_s_lock.c
11305 --- php-5.1.6.old/ext/apc/pgsql_s_lock.c 1969-12-31 18:00:00.000000000 -0600
11306 +++ php-5.1.6/ext/apc/pgsql_s_lock.c 2007-04-02 18:05:30.000000000 -0500
11309 + +----------------------------------------------------------------------+
11311 + +----------------------------------------------------------------------+
11312 + | Copyright (c) 2007 The PHP Group |
11313 + +----------------------------------------------------------------------+
11314 + | This source file is subject to version 3.01 of the PHP license, |
11315 + | that is bundled with this package in the file LICENSE, and is |
11316 + | available through the world-wide-web at the following url: |
11317 + | http://www.php.net/license/3_01.txt |
11318 + | If you did not receive a copy of the PHP license and are unable to |
11319 + | obtain it through the world-wide-web, please send a note to |
11320 + | license@php.net so we can mail you a copy immediately. |
11321 + +----------------------------------------------------------------------+
11322 + | The following code was ported from the PostgreSQL project, please |
11323 + | see appropriate copyright notices that follow. |
11324 + | Initial conversion by Brian Shire <shire@php.net> |
11325 + +----------------------------------------------------------------------+
11329 +/* $Id: pgsql_s_lock.c,v 3.2 2007/02/25 05:19:11 shire Exp $ */
11331 +/*-------------------------------------------------------------------------
11334 + * Hardware-dependent implementation of spinlocks.
11337 + * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
11338 + * Portions Copyright (c) 1994, Regents of the University of California
11342 + * $PostgreSQL: pgsql/src/backend/storage/lmgr/s_lock.c,v 1.47 2006/10/04 00:29:58 momjian Exp $
11344 + *-------------------------------------------------------------------------
11346 +/* #include "postgres.h" -- Removed for APC */
11348 +/* -- Added for APC -- */
11350 +#ifdef APC_SPIN_LOCKS
11352 +#ifdef S_LOCK_TEST
11353 +#include <stdio.h>
11356 +#include <sys/select.h>
11361 +#include <unistd.h>
11363 +/* #include "storage/s_lock.h" -- Removed for APC */
11364 +#include "pgsql_s_lock.h"
11366 +static int spins_per_delay = DEFAULT_SPINS_PER_DELAY;
11369 +/* -- APC specific additions ------------------------------*/
11370 +/* The following dependencies have been copied from
11371 + * other pgsql source files. The original locations
11372 + * have been noted.
11375 +/* -- from include/c.h -- */
11384 +/* -- from include/pg_config_manual.h -- */
11385 +#define MAX_RANDOM_VALUE (0x7FFFFFFF)
11389 + * Return the maximum of two numbers.
11391 +#define Max(x, y) ((x) > (y) ? (x) : (y))
11393 +/* -- from include/c.h -- */
11396 + * Return the minimum of two numbers.
11398 +#define Min(x, y) ((x) < (y) ? (x) : (y))
11401 +/* -- from backend/port/win32/signal.c -- */
11403 + * pg_usleep --- delay the specified number of microseconds.
11405 + * NOTE: although the delay is specified in microseconds, the effective
11406 + * resolution is only 1/HZ, or 10 milliseconds, on most Unixen. Expect
11407 + * the requested delay to be rounded up to the next resolution boundary.
11409 + * On machines where "long" is 32 bits, the maximum delay is ~2000 seconds.
11412 +pg_usleep(long microsec)
11414 + if (microsec > 0)
11417 + struct timeval delay;
11419 + delay.tv_sec = microsec / 1000000L;
11420 + delay.tv_usec = microsec % 1000000L;
11421 + (void) select(0, NULL, NULL, NULL, &delay);
11423 + SleepEx((microsec < 500 ? 1 : (microsec + 500) / 1000), FALSE);
11428 +/* -- End APC specific additions ------------------------------*/
11432 + * s_lock_stuck() - complain about a stuck spinlock
11435 +s_lock_stuck(volatile slock_t *lock, const char *file, int line)
11437 +#if defined(S_LOCK_TEST)
11439 + "\nStuck spinlock (%p) detected at %s:%d.\n",
11440 + lock, file, line);
11443 + /* -- Removed for APC
11444 + elog(PANIC, "stuck spinlock (%p) detected at %s:%d",
11445 + lock, file, line);
11447 + apc_eprint("Stuck spinlock (%p) detected", lock);
11453 + * s_lock(lock) - platform-independent portion of waiting for a spinlock.
11456 +s_lock(volatile slock_t *lock, const char *file, int line)
11459 + * We loop tightly for awhile, then delay using pg_usleep() and try again.
11460 + * Preferably, "awhile" should be a small multiple of the maximum time we
11461 + * expect a spinlock to be held. 100 iterations seems about right as an
11462 + * initial guess. However, on a uniprocessor the loop is a waste of
11463 + * cycles, while in a multi-CPU scenario it's usually better to spin a bit
11464 + * longer than to call the kernel, so we try to adapt the spin loop count
11465 + * depending on whether we seem to be in a uniprocessor or multiprocessor.
11467 + * Note: you might think MIN_SPINS_PER_DELAY should be just 1, but you'd
11468 + * be wrong; there are platforms where that can result in a "stuck
11469 + * spinlock" failure. This has been seen particularly on Alphas; it seems
11470 + * that the first TAS after returning from kernel space will always fail
11471 + * on that hardware.
11473 + * Once we do decide to block, we use randomly increasing pg_usleep()
11474 + * delays. The first delay is 1 msec, then the delay randomly increases to
11475 + * about one second, after which we reset to 1 msec and start again. The
11476 + * idea here is that in the presence of heavy contention we need to
11477 + * increase the delay, else the spinlock holder may never get to run and
11478 + * release the lock. (Consider situation where spinlock holder has been
11479 + * nice'd down in priority by the scheduler --- it will not get scheduled
11480 + * until all would-be acquirers are sleeping, so if we always use a 1-msec
11481 + * sleep, there is a real possibility of starvation.) But we can't just
11482 + * clamp the delay to an upper bound, else it would take a long time to
11483 + * make a reasonable number of tries.
11485 + * We time out and declare error after NUM_DELAYS delays (thus, exactly
11486 + * that many tries). With the given settings, this will usually take 2 or
11487 + * so minutes. It seems better to fix the total number of tries (and thus
11488 + * the probability of unintended failure) than to fix the total time
11491 + * The pg_usleep() delays are measured in milliseconds because 1 msec is a
11492 + * common resolution limit at the OS level for newer platforms. On older
11493 + * platforms the resolution limit is usually 10 msec, in which case the
11494 + * total delay before timeout will be a bit more.
11496 +#define MIN_SPINS_PER_DELAY 10
11497 +#define MAX_SPINS_PER_DELAY 1000
11498 +#define NUM_DELAYS 1000
11499 +#define MIN_DELAY_MSEC 1
11500 +#define MAX_DELAY_MSEC 1000
11504 + int cur_delay = 0;
11506 + while (TAS(lock))
11508 + /* CPU-specific delay each time through the loop */
11511 + /* Block the process every spins_per_delay tries */
11512 + if (++spins >= spins_per_delay)
11514 + if (++delays > NUM_DELAYS)
11515 + s_lock_stuck(lock, file, line);
11517 + if (cur_delay == 0) /* first time to delay? */
11518 + cur_delay = MIN_DELAY_MSEC;
11520 + pg_usleep(cur_delay * 1000L);
11522 +#if defined(S_LOCK_TEST)
11523 + fprintf(stdout, "*");
11527 + /* increase delay by a random fraction between 1X and 2X */
11528 + cur_delay += (int) (cur_delay *
11529 + ((double) random() / (double) MAX_RANDOM_VALUE) + 0.5);
11530 + /* wrap back to minimum delay when max is exceeded */
11531 + if (cur_delay > MAX_DELAY_MSEC)
11532 + cur_delay = MIN_DELAY_MSEC;
11539 + * If we were able to acquire the lock without delaying, it's a good
11540 + * indication we are in a multiprocessor. If we had to delay, it's a sign
11541 + * (but not a sure thing) that we are in a uniprocessor. Hence, we
11542 + * decrement spins_per_delay slowly when we had to delay, and increase it
11543 + * rapidly when we didn't. It's expected that spins_per_delay will
11544 + * converge to the minimum value on a uniprocessor and to the maximum
11545 + * value on a multiprocessor.
11547 + * Note: spins_per_delay is local within our current process. We want to
11548 + * average these observations across multiple backends, since it's
11549 + * relatively rare for this function to even get entered, and so a single
11550 + * backend might not live long enough to converge on a good value. That
11551 + * is handled by the two routines below.
11553 + if (cur_delay == 0)
11555 + /* we never had to delay */
11556 + if (spins_per_delay < MAX_SPINS_PER_DELAY)
11557 + spins_per_delay = Min(spins_per_delay + 100, MAX_SPINS_PER_DELAY);
11561 + if (spins_per_delay > MIN_SPINS_PER_DELAY)
11562 + spins_per_delay = Max(spins_per_delay - 1, MIN_SPINS_PER_DELAY);
11567 +#if 0 /* -- APC doesn't use the set_spins_per_delay or update_spins_per_delay -- */
11569 + * Set local copy of spins_per_delay during backend startup.
11571 + * NB: this has to be pretty fast as it is called while holding a spinlock
11574 +set_spins_per_delay(int shared_spins_per_delay)
11576 + spins_per_delay = shared_spins_per_delay;
11580 + * Update shared estimate of spins_per_delay during backend exit.
11582 + * NB: this has to be pretty fast as it is called while holding a spinlock
11585 +update_spins_per_delay(int shared_spins_per_delay)
11588 + * We use an exponential moving average with a relatively slow adaption
11589 + * rate, so that noise in any one backend's result won't affect the shared
11590 + * value too much. As long as both inputs are within the allowed range,
11591 + * the result must be too, so we need not worry about clamping the result.
11593 + * We deliberately truncate rather than rounding; this is so that single
11594 + * adjustments inside a backend can affect the shared estimate (see the
11595 + * asymmetric adjustment rules above).
11597 + return (shared_spins_per_delay * 15 + spins_per_delay) / 16;
11602 + * Various TAS implementations that cannot live in s_lock.h as no inline
11603 + * definition exists (yet).
11604 + * In the future, get rid of tas.[cso] and fold it into this file.
11606 + * If you change something here, you will likely need to modify s_lock.h too,
11607 + * because the definitions for these are split between this file and s_lock.h.
11611 +#ifdef HAVE_SPINLOCKS /* skip spinlocks if requested */
11614 +#if defined(__GNUC__)
11617 + * All the gcc flavors that are not inlined
11622 + * Note: all the if-tests here probably ought to be testing gcc version
11623 + * rather than platform, but I don't have adequate info to know what to
11624 + * write. Ideally we'd flush all this in favor of the inline version.
11626 +#if defined(__m68k__) && !defined(__linux__)
11627 +/* really means: extern int tas(slock_t* **lock); */
11631 + __asm__ __volatile__(
11632 +#if defined(__NetBSD__) && defined(__ELF__)
11633 +/* no underscore for label and % for registers */
11637 + movel %sp@(0x4),%a0 \n\
11640 + moveq #-128,%d0 \n\
11649 + movel sp@(0x4),a0 \n\
11652 + moveq #-128,d0 \n\
11657 +#endif /* __NetBSD__ && __ELF__ */
11660 +#endif /* __m68k__ && !__linux__ */
11661 +#else /* not __GNUC__ */
11670 +tas_dummy() /* really means: extern int tas(slock_t
11676 + asm("|#PROC# 04");
11677 + asm(" .globl _tas");
11679 + asm("|#PROLOGUE# 1");
11680 + asm(" movel sp@(0x4),a0");
11682 + asm(" beq LLA1");
11683 + asm(" moveq #-128,d0");
11686 + asm(" moveq #0,d0");
11691 +#endif /* not __GNUC__ */
11692 +#endif /* HAVE_SPINLOCKS */
11696 +/*****************************************************************************/
11697 +#if defined(S_LOCK_TEST)
11700 + * test program for verifying a port's spinlock support.
11703 +struct test_lock_struct
11710 +volatile struct test_lock_struct test_lock;
11715 + srandom((unsigned int) time(NULL));
11717 + test_lock.pad1 = test_lock.pad2 = 0x44;
11719 + S_INIT_LOCK(&test_lock.lock);
11721 + if (test_lock.pad1 != 0x44 || test_lock.pad2 != 0x44)
11723 + printf("S_LOCK_TEST: failed, declared datatype is wrong size\n");
11727 + if (!S_LOCK_FREE(&test_lock.lock))
11729 + printf("S_LOCK_TEST: failed, lock not initialized\n");
11733 + S_LOCK(&test_lock.lock);
11735 + if (test_lock.pad1 != 0x44 || test_lock.pad2 != 0x44)
11737 + printf("S_LOCK_TEST: failed, declared datatype is wrong size\n");
11741 + if (S_LOCK_FREE(&test_lock.lock))
11743 + printf("S_LOCK_TEST: failed, lock not locked\n");
11747 + S_UNLOCK(&test_lock.lock);
11749 + if (test_lock.pad1 != 0x44 || test_lock.pad2 != 0x44)
11751 + printf("S_LOCK_TEST: failed, declared datatype is wrong size\n");
11755 + if (!S_LOCK_FREE(&test_lock.lock))
11757 + printf("S_LOCK_TEST: failed, lock not unlocked\n");
11761 + S_LOCK(&test_lock.lock);
11763 + if (test_lock.pad1 != 0x44 || test_lock.pad2 != 0x44)
11765 + printf("S_LOCK_TEST: failed, declared datatype is wrong size\n");
11769 + if (S_LOCK_FREE(&test_lock.lock))
11771 + printf("S_LOCK_TEST: failed, lock not re-locked\n");
11775 + printf("S_LOCK_TEST: this will print %d stars and then\n", NUM_DELAYS);
11776 + printf(" exit with a 'stuck spinlock' message\n");
11777 + printf(" if S_LOCK() and TAS() are working.\n");
11780 + s_lock(&test_lock.lock, __FILE__, __LINE__);
11782 + printf("S_LOCK_TEST: failed, lock not locked\n");
11786 +#endif /* S_LOCK_TEST */
11788 +#endif /* APC_SPIN_LOCKS */
11789 diff -ruN php-5.1.6.old/ext/apc/pgsql_s_lock.h php-5.1.6/ext/APC/pgsql_s_lock.h
11790 --- php-5.1.6.old/ext/apc/pgsql_s_lock.h 1969-12-31 18:00:00.000000000 -0600
11791 +++ php-5.1.6/ext/apc/pgsql_s_lock.h 2007-04-02 18:05:30.000000000 -0500
11794 + +----------------------------------------------------------------------+
11796 + +----------------------------------------------------------------------+
11797 + | Copyright (c) 2007 The PHP Group |
11798 + +----------------------------------------------------------------------+
11799 + | This source file is subject to version 3.01 of the PHP license, |
11800 + | that is bundled with this package in the file LICENSE, and is |
11801 + | available through the world-wide-web at the following url: |
11802 + | http://www.php.net/license/3_01.txt |
11803 + | If you did not receive a copy of the PHP license and are unable to |
11804 + | obtain it through the world-wide-web, please send a note to |
11805 + | license@php.net so we can mail you a copy immediately. |
11806 + +----------------------------------------------------------------------+
11807 + | The following code was ported from the PostgreSQL project, please |
11808 + | see appropriate copyright notices that follow. |
11809 + | Initial conversion by Brian Shire <shire@php.net> |
11810 + +----------------------------------------------------------------------+
11814 +/* $Id: pgsql_s_lock.h,v 3.3 2007/02/16 21:28:04 shire Exp $ */
11816 +/*-------------------------------------------------------------------------
11819 + * Hardware-dependent implementation of spinlocks.
11821 + * NOTE: none of the macros in this file are intended to be called directly.
11822 + * Call them through the hardware-independent macros in spin.h.
11824 + * The following hardware-dependent macros must be provided for each
11825 + * supported platform:
11827 + * void S_INIT_LOCK(slock_t *lock)
11828 + * Initialize a spinlock (to the unlocked state).
11830 + * void S_LOCK(slock_t *lock)
11831 + * Acquire a spinlock, waiting if necessary.
11832 + * Time out and abort() if unable to acquire the lock in a
11833 + * "reasonable" amount of time --- typically ~ 1 minute.
11835 + * void S_UNLOCK(slock_t *lock)
11836 + * Unlock a previously acquired lock.
11838 + * bool S_LOCK_FREE(slock_t *lock)
11839 + * Tests if the lock is free. Returns TRUE if free, FALSE if locked.
11840 + * This does *not* change the state of the lock.
11842 + * void SPIN_DELAY(void)
11843 + * Delay operation to occur inside spinlock wait loop.
11845 + * Note to implementors: there are default implementations for all these
11846 + * macros at the bottom of the file. Check if your platform can use
11847 + * these or needs to override them.
11849 + * Usually, S_LOCK() is implemented in terms of an even lower-level macro
11852 + * int TAS(slock_t *lock)
11853 + * Atomic test-and-set instruction. Attempt to acquire the lock,
11854 + * but do *not* wait. Returns 0 if successful, nonzero if unable
11855 + * to acquire the lock.
11857 + * TAS() is NOT part of the API, and should never be called directly.
11859 + * CAUTION: on some platforms TAS() may sometimes report failure to acquire
11860 + * a lock even when the lock is not locked. For example, on Alpha TAS()
11861 + * will "fail" if interrupted. Therefore TAS() should always be invoked
11862 + * in a retry loop, even if you are certain the lock is free.
11864 + * ANOTHER CAUTION: be sure that TAS() and S_UNLOCK() represent sequence
11865 + * points, ie, loads and stores of other values must not be moved across
11866 + * a lock or unlock. In most cases it suffices to make the operation be
11867 + * done through a "volatile" pointer.
11869 + * On most supported platforms, TAS() uses a tas() function written
11870 + * in assembly language to execute a hardware atomic-test-and-set
11871 + * instruction. Equivalent OS-supplied mutex routines could be used too.
11873 + * If no system-specific TAS() is available (ie, HAVE_SPINLOCKS is not
11874 + * defined), then we fall back on an emulation that uses SysV semaphores
11875 + * (see spin.c). This emulation will be MUCH MUCH slower than a proper TAS()
11876 + * implementation, because of the cost of a kernel call per lock or unlock.
11877 + * An old report is that Postgres spends around 40% of its time in semop(2)
11878 + * when using the SysV semaphore code.
11881 + * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
11882 + * Portions Copyright (c) 1994, Regents of the University of California
11884 + * $PostgreSQL: pgsql/src/include/storage/s_lock.h,v 1.157 2006/06/07 22:24:45 momjian Exp $
11886 + *-------------------------------------------------------------------------
11891 +/** APC namespace protection ************************************************/
11892 +/* hack to protect against any possible runtime namespace collisions...*/
11893 +#define pg_usleep apc_spin_pg_usleep
11894 +#define s_lock apc_spin_s_lock
11895 +#define spins_per_delay apc_spin_spins_per_delay
11896 +/****************************************************************************/
11899 +/* #include "storage/pg_sema.h" -- Removed for APC */
11901 +#define HAVE_SPINLOCKS 1 /* -- Added for APC */
11903 +#ifdef HAVE_SPINLOCKS /* skip spinlocks if requested */
11906 +#if defined(__GNUC__) || defined(__ICC)
11907 +/*************************************************************************
11908 + * All the gcc inlines
11909 + * Gcc consistently defines the CPU as __cpu__.
11910 + * Other compilers use __cpu or __cpu__ so we test for both in those cases.
11914 + * Standard gcc asm format (assuming "volatile slock_t *lock"):
11916 + __asm__ __volatile__(
11917 + " instruction \n"
11918 + " instruction \n"
11919 + " instruction \n"
11920 +: "=r"(_res), "+m"(*lock) // return register, in/out lock value
11921 +: "r"(lock) // lock pointer, in input register
11922 +: "memory", "cc"); // show clobbered registers here
11924 + * The output-operands list (after first colon) should always include
11925 + * "+m"(*lock), whether or not the asm code actually refers to this
11926 + * operand directly. This ensures that gcc believes the value in the
11927 + * lock variable is used and set by the asm code. Also, the clobbers
11928 + * list (after third colon) should always include "memory"; this prevents
11929 + * gcc from thinking it can cache the values of shared-memory fields
11930 + * across the asm code. Add "cc" if your asm code changes the condition
11931 + * code register, and also list any temp registers the code uses.
11936 +#ifdef __i386__ /* 32-bit i386 */
11937 +#define HAS_TEST_AND_SET
11939 +typedef unsigned char slock_t;
11941 +#define TAS(lock) tas(lock)
11943 +static __inline__ int
11944 +tas(volatile slock_t *lock)
11946 + register slock_t _res = 1;
11949 + * Use a non-locking test before asserting the bus lock. Note that the
11950 + * extra test appears to be a small loss on some x86 platforms and a small
11951 + * win on others; it's by no means clear that we should keep it.
11953 + __asm__ __volatile__(
11957 + " xchgb %0,%1 \n"
11959 +: "+q"(_res), "+m"(*lock)
11961 +: "memory", "cc");
11962 + return (int) _res;
11965 +#define SPIN_DELAY() spin_delay()
11967 +static __inline__ void
11971 + * This sequence is equivalent to the PAUSE instruction ("rep" is
11972 + * ignored by old IA32 processors if the following instruction is
11973 + * not a string operation); the IA-32 Architecture Software
11974 + * Developer's Manual, Vol. 3, Section 7.7.2 describes why using
11975 + * PAUSE in the inner loop of a spin lock is necessary for good
11978 + * The PAUSE instruction improves the performance of IA-32
11979 + * processors supporting Hyper-Threading Technology when
11980 + * executing spin-wait loops and other routines where one
11981 + * thread is accessing a shared lock or semaphore in a tight
11982 + * polling loop. When executing a spin-wait loop, the
11983 + * processor can suffer a severe performance penalty when
11984 + * exiting the loop because it detects a possible memory order
11985 + * violation and flushes the core processor's pipeline. The
11986 + * PAUSE instruction provides a hint to the processor that the
11987 + * code sequence is a spin-wait loop. The processor uses this
11988 + * hint to avoid the memory order violation and prevent the
11989 + * pipeline flush. In addition, the PAUSE instruction
11990 + * de-pipelines the spin-wait loop to prevent it from
11991 + * consuming execution resources excessively.
11993 + __asm__ __volatile__(
11997 +#endif /* __i386__ */
12000 +#ifdef __x86_64__ /* AMD Opteron, Intel EM64T */
12001 +#define HAS_TEST_AND_SET
12003 +typedef unsigned char slock_t;
12005 +#define TAS(lock) tas(lock)
12007 +static __inline__ int
12008 +tas(volatile slock_t *lock)
12010 + register slock_t _res = 1;
12013 + * On Opteron, using a non-locking test before the locking instruction
12014 + * is a huge loss. On EM64T, it appears to be a wash or small loss,
12015 + * so we needn't bother to try to distinguish the sub-architectures.
12017 + __asm__ __volatile__(
12019 + " xchgb %0,%1 \n"
12020 +: "+q"(_res), "+m"(*lock)
12022 +: "memory", "cc");
12023 + return (int) _res;
12026 +#define SPIN_DELAY() spin_delay()
12028 +static __inline__ void
12032 + * Adding a PAUSE in the spin delay loop is demonstrably a no-op on
12033 + * Opteron, but it may be of some use on EM64T, so we keep it.
12035 + __asm__ __volatile__(
12039 +#endif /* __x86_64__ */
12042 +#if defined(__ia64__) || defined(__ia64) /* Intel Itanium */
12043 +#define HAS_TEST_AND_SET
12045 +typedef unsigned int slock_t;
12047 +#define TAS(lock) tas(lock)
12049 +#ifndef __INTEL_COMPILER
12051 +static __inline__ int
12052 +tas(volatile slock_t *lock)
12056 + __asm__ __volatile__(
12057 + " xchg4 %0=%1,%2 \n"
12058 +: "=r"(ret), "+m"(*lock)
12061 + return (int) ret;
12064 +#else /* __INTEL_COMPILER */
12066 +static __inline__ int
12067 +tas(volatile slock_t *lock)
12071 + ret = _InterlockedExchange(lock,1); /* this is a xchg asm macro */
12076 +#endif /* __INTEL_COMPILER */
12077 +#endif /* __ia64__ || __ia64 */
12080 +#if defined(__arm__) || defined(__arm)
12081 +#define HAS_TEST_AND_SET
12083 +typedef unsigned char slock_t;
12085 +#define TAS(lock) tas(lock)
12087 +static __inline__ int
12088 +tas(volatile slock_t *lock)
12090 + register slock_t _res = 1;
12092 + __asm__ __volatile__(
12093 + " swpb %0, %0, [%2] \n"
12094 +: "+r"(_res), "+m"(*lock)
12097 + return (int) _res;
12100 +#endif /* __arm__ */
12103 +/* S/390 and S/390x Linux (32- and 64-bit zSeries) */
12104 +#if defined(__s390__) || defined(__s390x__)
12105 +#define HAS_TEST_AND_SET
12107 +typedef unsigned int slock_t;
12109 +#define TAS(lock) tas(lock)
12111 +static __inline__ int
12112 +tas(volatile slock_t *lock)
12116 + __asm__ __volatile__(
12117 + " cs %0,%3,0(%2) \n"
12118 +: "+d"(_res), "+m"(*lock)
12119 +: "a"(lock), "d"(1)
12120 +: "memory", "cc");
12124 +#endif /* __s390__ || __s390x__ */
12127 +#if defined(__sparc__) /* Sparc */
12128 +#define HAS_TEST_AND_SET
12130 +typedef unsigned char slock_t;
12132 +#define TAS(lock) tas(lock)
12134 +static __inline__ int
12135 +tas(volatile slock_t *lock)
12137 + register slock_t _res;
12140 + * See comment in /pg/backend/port/tas/solaris_sparc.s for why this
12141 + * uses "ldstub", and that file uses "cas". gcc currently generates
12142 + * sparcv7-targeted binaries, so "cas" use isn't possible.
12144 + __asm__ __volatile__(
12145 + " ldstub [%2], %0 \n"
12146 +: "=r"(_res), "+m"(*lock)
12149 + return (int) _res;
12152 +#endif /* __sparc__ */
12156 +#if defined(__ppc__) || defined(__powerpc__) || defined(__ppc64__) || defined(__powerpc64__)
12157 +#define HAS_TEST_AND_SET
12159 +#if defined(__ppc64__) || defined(__powerpc64__)
12160 +typedef unsigned long slock_t;
12162 +typedef unsigned int slock_t;
12165 +#define TAS(lock) tas(lock)
12167 + * NOTE: per the Enhanced PowerPC Architecture manual, v1.0 dated 7-May-2002,
12168 + * an isync is a sufficient synchronization barrier after a lwarx/stwcx loop.
12170 +static __inline__ int
12171 +tas(volatile slock_t *lock)
12176 + __asm__ __volatile__(
12177 +" lwarx %0,0,%3 \n"
12180 +" addi %0,%0,1 \n"
12181 +" stwcx. %0,0,%3 \n"
12190 +: "=&r"(_t), "=r"(_res), "+m"(*lock)
12192 +: "memory", "cc");
12196 +/* PowerPC S_UNLOCK is almost standard but requires a "sync" instruction */
12197 +#define S_UNLOCK(lock) \
12200 + __asm__ __volatile__ (" sync \n"); \
12201 + *((volatile slock_t *) (lock)) = 0; \
12204 +#endif /* powerpc */
12207 +/* Linux Motorola 68k */
12208 +#if (defined(__mc68000__) || defined(__m68k__)) && defined(__linux__)
12209 +#define HAS_TEST_AND_SET
12211 +typedef unsigned char slock_t;
12213 +#define TAS(lock) tas(lock)
12215 +static __inline__ int
12216 +tas(volatile slock_t *lock)
12220 + __asm__ __volatile__(
12224 +: "=d"(rv), "+m"(*lock)
12226 +: "memory", "cc");
12230 +#endif /* (__mc68000__ || __m68k__) && __linux__ */
12234 + * VAXen -- even multiprocessor ones
12235 + * (thanks to Tom Ivar Helbekkmo)
12237 +#if defined(__vax__)
12238 +#define HAS_TEST_AND_SET
12240 +typedef unsigned char slock_t;
12242 +#define TAS(lock) tas(lock)
12244 +static __inline__ int
12245 +tas(volatile slock_t *lock)
12247 + register int _res;
12249 + __asm__ __volatile__(
12250 + " movl $1, %0 \n"
12251 + " bbssi $0, (%2), 1f \n"
12254 +: "=&r"(_res), "+m"(*lock)
12260 +#endif /* __vax__ */
12263 +#if defined(__ns32k__) /* National Semiconductor 32K */
12264 +#define HAS_TEST_AND_SET
12266 +typedef unsigned char slock_t;
12268 +#define TAS(lock) tas(lock)
12270 +static __inline__ int
12271 +tas(volatile slock_t *lock)
12273 + register int _res;
12275 + __asm__ __volatile__(
12276 + " sbitb 0, %1 \n"
12278 +: "=r"(_res), "+m"(*lock)
12284 +#endif /* __ns32k__ */
12287 +#if defined(__alpha) || defined(__alpha__) /* Alpha */
12289 + * Correct multi-processor locking methods are explained in section 5.5.3
12290 + * of the Alpha AXP Architecture Handbook, which at this writing can be
12291 + * found at ftp://ftp.netbsd.org/pub/NetBSD/misc/dec-docs/index.html.
12292 + * For gcc we implement the handbook's code directly with inline assembler.
12294 +#define HAS_TEST_AND_SET
12296 +typedef unsigned long slock_t;
12298 +#define TAS(lock) tas(lock)
12300 +static __inline__ int
12301 +tas(volatile slock_t *lock)
12303 + register slock_t _res;
12305 + __asm__ __volatile__(
12308 + " ldq_l %0, %1 \n"
12311 + " stq_c $0, %1 \n"
12315 + "2: mov 1, %0 \n"
12317 +: "=&r"(_res), "+m"(*lock)
12320 + return (int) _res;
12323 +#define S_UNLOCK(lock) \
12326 + __asm__ __volatile__ (" mb \n"); \
12327 + *((volatile slock_t *) (lock)) = 0; \
12330 +#endif /* __alpha || __alpha__ */
12333 +#if defined(__mips__) && !defined(__sgi) /* non-SGI MIPS */
12334 +/* Note: on SGI we use the OS' mutex ABI, see below */
12335 +/* Note: R10000 processors require a separate SYNC */
12336 +#define HAS_TEST_AND_SET
12338 +typedef unsigned int slock_t;
12340 +#define TAS(lock) tas(lock)
12342 +static __inline__ int
12343 +tas(volatile slock_t *lock)
12345 + register volatile slock_t *_l = lock;
12346 + register int _res;
12347 + register int _tmp;
12349 + __asm__ __volatile__(
12352 + " .set noreorder \n"
12353 + " .set nomacro \n"
12355 + " or %1, %0, 1 \n"
12358 + " or %0, %0, %1 \n"
12361 +: "=&r" (_res), "=&r" (_tmp), "+R" (*_l)
12367 +/* MIPS S_UNLOCK is almost standard but requires a "sync" instruction */
12368 +#define S_UNLOCK(lock) \
12371 + __asm__ __volatile__( \
12372 + " .set push \n" \
12373 + " .set mips2 \n" \
12374 + " .set noreorder \n" \
12375 + " .set nomacro \n" \
12378 + *((volatile slock_t *) (lock)) = 0; \
12381 +#endif /* __mips__ && !__sgi */
12384 +/* These live in s_lock.c, but only for gcc */
12387 +#if defined(__m68k__) && !defined(__linux__) /* non-Linux Motorola 68k */
12388 +#define HAS_TEST_AND_SET
12390 +typedef unsigned char slock_t;
12394 +#endif /* __GNUC__ */
12399 + * ---------------------------------------------------------------------
12400 + * Platforms that use non-gcc inline assembly:
12401 + * ---------------------------------------------------------------------
12404 +#if !defined(HAS_TEST_AND_SET) /* We didn't trigger above, let's try here */
12407 +#if defined(USE_UNIVEL_CC) /* Unixware compiler */
12408 +#define HAS_TEST_AND_SET
12410 +typedef unsigned char slock_t;
12412 +#define TAS(lock) tas(lock)
12415 +tas(volatile slock_t *s_lock)
12417 +/* UNIVEL wants %mem in column 1, so we don't pg_indent this file */
12420 + movl s_lock, %ebx
12423 + xchgb %al, (%ebx)
12427 +#endif /* defined(USE_UNIVEL_CC) */
12430 +#if defined(__alpha) || defined(__alpha__) /* Tru64 Unix Alpha compiler */
12432 + * The Tru64 compiler doesn't support gcc-style inline asm, but it does
12433 + * have some builtin functions that accomplish much the same results.
12434 + * For simplicity, slock_t is defined as long (ie, quadword) on Alpha
12435 + * regardless of the compiler in use. LOCK_LONG and UNLOCK_LONG only
12436 + * operate on an int (ie, longword), but that's OK as long as we define
12437 + * S_INIT_LOCK to zero out the whole quadword.
12439 +#define HAS_TEST_AND_SET
12441 +typedef unsigned long slock_t;
12443 +#include <alpha/builtins.h>
12444 +#define S_INIT_LOCK(lock) (*(lock) = 0)
12445 +#define TAS(lock) (__LOCK_LONG_RETRY((lock), 1) == 0)
12446 +#define S_UNLOCK(lock) __UNLOCK_LONG(lock)
12448 +#endif /* __alpha || __alpha__ */
12451 +#if defined(__hppa) || defined(__hppa__) /* HP PA-RISC, GCC and HP compilers */
12455 + * See src/backend/port/hpux/tas.c.template for details about LDCWX. Because
12456 + * LDCWX requires a 16-byte-aligned address, we declare slock_t as a 16-byte
12457 + * struct. The active word in the struct is whichever has the aligned address;
12458 + * the other three words just sit at -1.
12460 + * When using gcc, we can inline the required assembly code.
12462 +#define HAS_TEST_AND_SET
12469 +#define TAS_ACTIVE_WORD(lock) ((volatile int *) (((long) (lock) + 15) & ~15))
12471 +#if defined(__GNUC__)
12473 +static __inline__ int
12474 +tas(volatile slock_t *lock)
12476 + volatile int *lockword = TAS_ACTIVE_WORD(lock);
12477 + register int lockval;
12479 + __asm__ __volatile__(
12480 + " ldcwx 0(0,%2),%0 \n"
12481 +: "=r"(lockval), "+m"(*lockword)
12484 + return (lockval == 0);
12487 +#endif /* __GNUC__ */
12489 +#define S_UNLOCK(lock) (*TAS_ACTIVE_WORD(lock) = -1)
12491 +#define S_INIT_LOCK(lock) \
12493 + volatile slock_t *lock_ = (lock); \
12494 + lock_->sema[0] = -1; \
12495 + lock_->sema[1] = -1; \
12496 + lock_->sema[2] = -1; \
12497 + lock_->sema[3] = -1; \
12500 +#define S_LOCK_FREE(lock) (*TAS_ACTIVE_WORD(lock) != 0)
12502 +#endif /* __hppa || __hppa__ */
12505 +#if defined(__hpux) && defined(__ia64) && !defined(__GNUC__)
12507 +#define HAS_TEST_AND_SET
12509 +typedef unsigned int slock_t;
12511 +#include <ia64/sys/inline.h>
12512 +#define TAS(lock) _Asm_xchg(_SZ_W, lock, 1, _LDHINT_NONE)
12514 +#endif /* HPUX on IA64, non gcc */
12517 +#if defined(__sgi) /* SGI compiler */
12520 + * slock_t is defined as a unsigned long. We use the standard SGI
12523 + * The following comment is left for historical reasons, but is probably
12524 + * not a good idea since the mutex ABI is supported.
12526 + * This stuff may be supplemented in the future with Masato Kataoka's MIPS-II
12527 + * assembly from his NECEWS SVR4 port, but we probably ought to retain this
12528 + * for the R3000 chips out there.
12530 +#define HAS_TEST_AND_SET
12532 +typedef unsigned long slock_t;
12534 +#include "mutex.h"
12535 +#define TAS(lock) (test_and_set(lock,1))
12536 +#define S_UNLOCK(lock) (test_then_and(lock,0))
12537 +#define S_INIT_LOCK(lock) (test_then_and(lock,0))
12538 +#define S_LOCK_FREE(lock) (test_then_add(lock,0) == 0)
12539 +#endif /* __sgi */
12542 +#if defined(sinix) /* Sinix */
12544 + * SINIX / Reliant UNIX
12545 + * slock_t is defined as a struct abilock_t, which has a single unsigned long
12546 + * member. (Basically same as SGI)
12548 +#define HAS_TEST_AND_SET
12550 +#include "abi_mutex.h"
12551 +typedef abilock_t slock_t;
12553 +#define TAS(lock) (!acquire_lock(lock))
12554 +#define S_UNLOCK(lock) release_lock(lock)
12555 +#define S_INIT_LOCK(lock) init_lock(lock)
12556 +#define S_LOCK_FREE(lock) (stat_lock(lock) == UNLOCKED)
12557 +#endif /* sinix */
12560 +#if defined(_AIX) /* AIX */
12564 +#define HAS_TEST_AND_SET
12566 +typedef unsigned int slock_t;
12568 +#define TAS(lock) _check_lock(lock, 0, 1)
12569 +#define S_UNLOCK(lock) _clear_lock(lock, 0)
12573 +#if defined (nextstep) /* Nextstep */
12574 +#define HAS_TEST_AND_SET
12576 +typedef struct mutex slock_t;
12578 +#define APC_SLOCK_NONBLOCKING_LOCK_AVAILABLE 0 /* -- APC: non-blocking lock not available in this case -- */
12580 +#define S_LOCK(lock) mutex_lock(lock)
12581 +#define S_UNLOCK(lock) mutex_unlock(lock)
12582 +#define S_INIT_LOCK(lock) mutex_init(lock)
12583 +/* For Mach, we have to delve inside the entrails of `struct mutex'. Ick! */
12584 +#define S_LOCK_FREE(alock) ((alock)->lock == 0)
12585 +#endif /* nextstep */
12588 +/* These are in s_lock.c */
12591 +#if defined(sun3) /* Sun3 */
12592 +#define HAS_TEST_AND_SET
12594 +typedef unsigned char slock_t;
12598 +#if defined(__sun) && (defined(__i386) || defined(__x86_64__) || defined(__sparc__) || defined(__sparc))
12599 +#define HAS_TEST_AND_SET
12601 +#if defined(__i386) || defined(__x86_64__) || defined(__sparcv9) || defined(__sparcv8plus)
12602 +typedef unsigned int slock_t;
12604 +typedef unsigned char slock_t;
12607 +extern slock_t pg_atomic_cas(volatile slock_t *lock, slock_t with,
12610 +#define TAS(a) (pg_atomic_cas((a), 1, 0) != 0)
12614 +#ifdef WIN32_ONLY_COMPILER
12615 +typedef LONG slock_t;
12617 +#define HAS_TEST_AND_SET
12618 +#define TAS(lock) (InterlockedCompareExchange(lock, 1, 0))
12620 +#define SPIN_DELAY() spin_delay()
12622 +static __forceinline void
12625 + /* See comment for gcc code. Same code, MASM syntax */
12632 +#endif /* !defined(HAS_TEST_AND_SET) */
12635 +/* Blow up if we didn't have any way to do spinlocks */
12636 +#ifndef HAS_TEST_AND_SET
12637 +/* -- APC: We have better options in APC than this, that should be specified explicitly so just fail out and notify the user -- */
12638 +#error Spin locking is not available on your platform, please select another locking method (see ./configure --help).
12639 +/* #error PostgreSQL does not have native spinlock support on this platform. To continue the compilation, rerun configure using --disable-spinlocks. However, performance will be poor. Please report this to pgsql-bugs@postgresql.org. */
12643 +#else /* !HAVE_SPINLOCKS */
12647 + * Fake spinlock implementation using semaphores --- slow and prone
12648 + * to fall foul of kernel limits on number of semaphores, so don't use this
12649 + * unless you must! The subroutines appear in spin.c.
12652 +/* -- Removed for APC
12653 +typedef PGSemaphoreData slock_t;
12655 +extern bool s_lock_free_sema(volatile slock_t *lock);
12656 +extern void s_unlock_sema(volatile slock_t *lock);
12657 +extern void s_init_lock_sema(volatile slock_t *lock);
12658 +extern int tas_sema(volatile slock_t *lock);
12660 +#define S_LOCK_FREE(lock) s_lock_free_sema(lock)
12661 +#define S_UNLOCK(lock) s_unlock_sema(lock)
12662 +#define S_INIT_LOCK(lock) s_init_lock_sema(lock)
12663 +#define TAS(lock) tas_sema(lock)
12666 +#endif /* HAVE_SPINLOCKS */
12670 + * Default Definitions - override these above as needed.
12673 +#define APC_SLOCK_NONBLOCKING_LOCK_AVAILABLE 1 /* -- APC: Non-blocking lock available for this case -- */
12675 +#if !defined(S_LOCK)
12676 +#define S_LOCK(lock) \
12679 + s_lock((lock), __FILE__, __LINE__); \
12681 +#endif /* S_LOCK */
12683 +#if !defined(S_LOCK_FREE)
12684 +#define S_LOCK_FREE(lock) (*(lock) == 0)
12685 +#endif /* S_LOCK_FREE */
12687 +#if !defined(S_UNLOCK)
12688 +#define S_UNLOCK(lock) (*((volatile slock_t *) (lock)) = 0)
12689 +#endif /* S_UNLOCK */
12691 +#if !defined(S_INIT_LOCK)
12692 +#define S_INIT_LOCK(lock) S_UNLOCK(lock)
12693 +#endif /* S_INIT_LOCK */
12695 +#if !defined(SPIN_DELAY)
12696 +#define SPIN_DELAY() ((void) 0)
12697 +#endif /* SPIN_DELAY */
12700 +extern int tas(volatile slock_t *lock); /* in port/.../tas.s, or
12703 +#define TAS(lock) tas(lock)
12708 + * Platform-independent out-of-line support routines
12710 +extern void s_lock(volatile slock_t *lock, const char *file, int line);
12712 +/* Support for dynamic adjustment of spins_per_delay */
12713 +#define DEFAULT_SPINS_PER_DELAY 100
12715 +#if 0 /* -- Removed from APC use -- */
12716 +extern void set_spins_per_delay(int shared_spins_per_delay);
12717 +extern int update_spins_per_delay(int shared_spins_per_delay);
12720 +#endif /* S_LOCK_H */
12721 diff -ruN php-5.1.6.old/ext/apc/php_apc.c php-5.1.6/ext/APC/php_apc.c
12722 --- php-5.1.6.old/ext/apc/php_apc.c 1969-12-31 18:00:00.000000000 -0600
12723 +++ php-5.1.6/ext/apc/php_apc.c 2007-04-02 18:05:30.000000000 -0500
12726 + +----------------------------------------------------------------------+
12728 + +----------------------------------------------------------------------+
12729 + | Copyright (c) 2006 The PHP Group |
12730 + +----------------------------------------------------------------------+
12731 + | This source file is subject to version 3.01 of the PHP license, |
12732 + | that is bundled with this package in the file LICENSE, and is |
12733 + | available through the world-wide-web at the following url: |
12734 + | http://www.php.net/license/3_01.txt |
12735 + | If you did not receive a copy of the PHP license and are unable to |
12736 + | obtain it through the world-wide-web, please send a note to |
12737 + | license@php.net so we can mail you a copy immediately. |
12738 + +----------------------------------------------------------------------+
12739 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
12740 + | Rasmus Lerdorf <rasmus@php.net> |
12741 + +----------------------------------------------------------------------+
12743 + This software was contributed to PHP by Community Connect Inc. in 2002
12744 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
12745 + Future revisions and derivatives of this source code must acknowledge
12746 + Community Connect Inc. as the original contributor of this module by
12747 + leaving this note intact in the source code.
12749 + All other licensing and usage conditions are those of the PHP Group.
12753 +/* $Id: php_apc.c,v 3.140 2007/03/28 07:14:54 gopalv Exp $ */
12755 +#include "apc_zend.h"
12756 +#include "apc_cache.h"
12757 +#include "apc_main.h"
12758 +#include "apc_sma.h"
12759 +#include "apc_lock.h"
12760 +#include "php_globals.h"
12761 +#include "php_ini.h"
12762 +#include "ext/standard/info.h"
12764 +#include "rfc1867.h"
12765 +#include "php_apc.h"
12766 +#if PHP_API_VERSION <= 20020918
12768 +#ifdef APC_PHP4_STAT
12770 +#include "httpd.h"
12775 +/* {{{ PHP_FUNCTION declarations */
12776 +PHP_FUNCTION(apc_cache_info);
12777 +PHP_FUNCTION(apc_clear_cache);
12778 +PHP_FUNCTION(apc_sma_info);
12779 +PHP_FUNCTION(apc_store);
12780 +PHP_FUNCTION(apc_fetch);
12781 +PHP_FUNCTION(apc_delete);
12782 +PHP_FUNCTION(apc_compile_file);
12783 +PHP_FUNCTION(apc_define_constants);
12784 +PHP_FUNCTION(apc_load_constants);
12785 +PHP_FUNCTION(apc_add);
12788 +/* {{{ ZEND_DECLARE_MODULE_GLOBALS(apc) */
12789 +ZEND_DECLARE_MODULE_GLOBALS(apc)
12791 +/* True globals */
12792 +apc_cache_t* apc_cache = NULL;
12793 +apc_cache_t* apc_user_cache = NULL;
12794 +void* apc_compiled_filters = NULL;
12796 +static void php_apc_init_globals(zend_apc_globals* apc_globals TSRMLS_DC)
12798 + apc_globals->filters = NULL;
12799 + apc_globals->initialized = 0;
12800 + apc_globals->cache_stack = apc_stack_create(0);
12801 + apc_globals->cache_by_default = 1;
12802 + apc_globals->slam_defense = 0;
12803 + apc_globals->mem_size_ptr = NULL;
12804 + apc_globals->fpstat = 1;
12805 + apc_globals->stat_ctime = 0;
12806 + apc_globals->write_lock = 1;
12807 + apc_globals->report_autofilter = 0;
12808 + apc_globals->apc_optimize_function = NULL;
12809 +#ifdef MULTIPART_EVENT_FORMDATA
12810 + apc_globals->rfc1867 = 0;
12812 + apc_globals->copied_zvals = NULL;
12813 +#ifdef ZEND_ENGINE_2
12814 + apc_globals->reserved_offset = -1;
12816 + apc_globals->localcache = 0;
12817 + apc_globals->localcache_size = 0;
12818 + apc_globals->lcache = NULL;
12821 +static void php_apc_shutdown_globals(zend_apc_globals* apc_globals TSRMLS_DC)
12823 + /* deallocate the ignore patterns */
12824 + if (apc_globals->filters != NULL) {
12826 + for (i=0; apc_globals->filters[i] != NULL; i++) {
12827 + apc_efree(apc_globals->filters[i]);
12829 + apc_efree(apc_globals->filters);
12832 + /* the stack should be empty */
12833 + assert(apc_stack_size(apc_globals->cache_stack) == 0);
12835 + /* apc cleanup */
12836 + apc_stack_destroy(apc_globals->cache_stack);
12838 + /* the rest of the globals are cleaned up in apc_module_shutdown() */
12845 +static PHP_INI_MH(OnUpdate_filters) /* {{{ */
12847 + APCG(filters) = apc_tokenize(new_value, ',');
12852 +static PHP_INI_MH(OnUpdateShmSegments) /* {{{ */
12855 + if(atoi(new_value)!=1) {
12856 + php_error_docref(NULL TSRMLS_CC, E_WARNING, "apc.shm_segments setting ignored in MMAP mode");
12858 + APCG(shm_segments) = 1;
12860 + APCG(shm_segments) = atoi(new_value);
12867 +#ifdef ZEND_ENGINE_2
12868 +#define OnUpdateInt OnUpdateLong
12872 +STD_PHP_INI_BOOLEAN("apc.enabled", "1", PHP_INI_SYSTEM, OnUpdateBool, enabled, zend_apc_globals, apc_globals)
12873 +STD_PHP_INI_ENTRY("apc.shm_segments", "1", PHP_INI_SYSTEM, OnUpdateShmSegments, shm_segments, zend_apc_globals, apc_globals)
12874 +STD_PHP_INI_ENTRY("apc.shm_size", "30", PHP_INI_SYSTEM, OnUpdateInt, shm_size, zend_apc_globals, apc_globals)
12875 +STD_PHP_INI_BOOLEAN("apc.include_once_override", "0", PHP_INI_SYSTEM, OnUpdateBool, include_once, zend_apc_globals, apc_globals)
12876 +STD_PHP_INI_ENTRY("apc.num_files_hint", "1000", PHP_INI_SYSTEM, OnUpdateInt, num_files_hint, zend_apc_globals, apc_globals)
12877 +STD_PHP_INI_ENTRY("apc.user_entries_hint", "4096", PHP_INI_SYSTEM, OnUpdateInt, user_entries_hint, zend_apc_globals, apc_globals)
12878 +STD_PHP_INI_ENTRY("apc.gc_ttl", "3600", PHP_INI_SYSTEM, OnUpdateInt, gc_ttl, zend_apc_globals, apc_globals)
12879 +STD_PHP_INI_ENTRY("apc.ttl", "0", PHP_INI_SYSTEM, OnUpdateInt, ttl, zend_apc_globals, apc_globals)
12880 +STD_PHP_INI_ENTRY("apc.user_ttl", "0", PHP_INI_SYSTEM, OnUpdateInt, user_ttl, zend_apc_globals, apc_globals)
12882 +STD_PHP_INI_ENTRY("apc.mmap_file_mask", NULL, PHP_INI_SYSTEM, OnUpdateString, mmap_file_mask, zend_apc_globals, apc_globals)
12884 +PHP_INI_ENTRY("apc.filters", NULL, PHP_INI_SYSTEM, OnUpdate_filters)
12885 +STD_PHP_INI_BOOLEAN("apc.cache_by_default", "1", PHP_INI_ALL, OnUpdateBool, cache_by_default, zend_apc_globals, apc_globals)
12886 +STD_PHP_INI_ENTRY("apc.slam_defense", "0", PHP_INI_SYSTEM, OnUpdateInt, slam_defense, zend_apc_globals, apc_globals)
12887 +STD_PHP_INI_ENTRY("apc.file_update_protection", "2", PHP_INI_SYSTEM, OnUpdateInt,file_update_protection, zend_apc_globals, apc_globals)
12888 +STD_PHP_INI_BOOLEAN("apc.enable_cli", "0", PHP_INI_SYSTEM, OnUpdateBool, enable_cli, zend_apc_globals, apc_globals)
12889 +STD_PHP_INI_ENTRY("apc.max_file_size", "1M", PHP_INI_SYSTEM, OnUpdateInt, max_file_size, zend_apc_globals, apc_globals)
12890 +STD_PHP_INI_BOOLEAN("apc.stat", "1", PHP_INI_SYSTEM, OnUpdateBool, fpstat, zend_apc_globals, apc_globals)
12891 +STD_PHP_INI_BOOLEAN("apc.stat_ctime", "0", PHP_INI_SYSTEM, OnUpdateBool, stat_ctime, zend_apc_globals, apc_globals)
12892 +STD_PHP_INI_BOOLEAN("apc.write_lock", "1", PHP_INI_SYSTEM, OnUpdateBool, write_lock, zend_apc_globals, apc_globals)
12893 +STD_PHP_INI_BOOLEAN("apc.report_autofilter", "0", PHP_INI_SYSTEM, OnUpdateBool, report_autofilter,zend_apc_globals, apc_globals)
12894 +#ifdef MULTIPART_EVENT_FORMDATA
12895 +STD_PHP_INI_BOOLEAN("apc.rfc1867", "0", PHP_INI_SYSTEM, OnUpdateBool, rfc1867, zend_apc_globals, apc_globals)
12897 +STD_PHP_INI_BOOLEAN("apc.localcache", "0", PHP_INI_SYSTEM, OnUpdateBool, localcache, zend_apc_globals, apc_globals)
12898 +STD_PHP_INI_ENTRY("apc.localcache.size", "512", PHP_INI_SYSTEM, OnUpdateInt, localcache_size, zend_apc_globals, apc_globals)
12903 +/* {{{ PHP_MINFO_FUNCTION(apc) */
12904 +static PHP_MINFO_FUNCTION(apc)
12906 + php_info_print_table_start();
12907 + php_info_print_table_row(2, "APC Support", APCG(enabled) ? "enabled" : "disabled");
12908 + php_info_print_table_row(2, "Version", APC_VERSION);
12910 + php_info_print_table_row(2, "MMAP Support", "Enabled");
12911 + php_info_print_table_row(2, "MMAP File Mask", APCG(mmap_file_mask));
12913 + php_info_print_table_row(2, "MMAP Support", "Disabled");
12916 + php_info_print_table_row(2, "Locking type", "IPC Semaphore");
12917 +#elif APC_FUTEX_LOCKS
12918 + php_info_print_table_row(2, "Locking type", "Linux Futex Locks");
12919 +#elif APC_PTHREADMUTEX_LOCKS
12920 + php_info_print_table_row(2, "Locking type", "pthread mutex Locks");
12921 +#elif APC_SPIN_LOCKS
12922 + php_info_print_table_row(2, "Locking type", "spin Locks");
12924 + php_info_print_table_row(2, "Locking type", "File Locks");
12926 + php_info_print_table_row(2, "Revision", "$Revision: 3.140 $");
12927 + php_info_print_table_row(2, "Build Date", __DATE__ " " __TIME__);
12928 + php_info_print_table_end();
12929 + DISPLAY_INI_ENTRIES();
12933 +#ifdef MULTIPART_EVENT_FORMDATA
12934 +extern int apc_rfc1867_progress(unsigned int event, void *event_data, void **extra TSRMLS_DC);
12937 +/* {{{ PHP_MINIT_FUNCTION(apc) */
12938 +static PHP_MINIT_FUNCTION(apc)
12940 + ZEND_INIT_MODULE_GLOBALS(apc, php_apc_init_globals, php_apc_shutdown_globals);
12942 + REGISTER_INI_ENTRIES();
12944 + /* Disable APC in cli mode unless overridden by apc.enable_cli */
12945 + if(!APCG(enable_cli) && !strcmp(sapi_module.name, "cli")) {
12946 + APCG(enabled) = 0;
12949 + if (APCG(enabled)) {
12950 + if(APCG(initialized)) {
12951 + apc_process_init(module_number TSRMLS_CC);
12953 + apc_module_init(module_number TSRMLS_CC);
12954 + apc_zend_init(TSRMLS_C);
12955 + apc_process_init(module_number TSRMLS_CC);
12956 +#ifdef MULTIPART_EVENT_FORMDATA
12957 + /* File upload progress tracking */
12958 + if(APCG(rfc1867)) {
12959 + php_rfc1867_callback = apc_rfc1867_progress;
12969 +/* {{{ PHP_MSHUTDOWN_FUNCTION(apc) */
12970 +static PHP_MSHUTDOWN_FUNCTION(apc)
12972 + if(APCG(enabled)) {
12973 + apc_process_shutdown(TSRMLS_C);
12974 + apc_zend_shutdown(TSRMLS_C);
12975 + apc_module_shutdown(TSRMLS_C);
12977 + php_apc_shutdown_globals(&apc_globals);
12981 + ts_free_id(apc_globals_id);
12983 + UNREGISTER_INI_ENTRIES();
12988 +/* {{{ PHP_RINIT_FUNCTION(apc) */
12989 +static PHP_RINIT_FUNCTION(apc)
12991 + if(APCG(enabled)) {
12992 + apc_request_init(TSRMLS_C);
12998 +/* {{{ PHP_RSHUTDOWN_FUNCTION(apc) */
12999 +static PHP_RSHUTDOWN_FUNCTION(apc)
13001 + if(APCG(enabled)) {
13002 + apc_request_shutdown(TSRMLS_C);
13008 +/* {{{ proto array apc_cache_info([string type] [, bool limited]) */
13009 +PHP_FUNCTION(apc_cache_info)
13011 + apc_cache_info_t* info;
13012 + apc_cache_link_t* p;
13014 + char *cache_type;
13016 + zend_bool limited=0;
13018 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sb", &cache_type, &ct_len, &limited) == FAILURE) {
13022 + if(ZEND_NUM_ARGS()) {
13023 + if(!strcasecmp(cache_type,"user")) {
13024 + info = apc_cache_info(apc_user_cache, limited);
13026 + info = apc_cache_info(apc_cache, limited);
13028 + } else info = apc_cache_info(apc_cache, limited);
13031 + php_error_docref(NULL TSRMLS_CC, E_WARNING, "No APC info available. Perhaps APC is not enabled? Check apc.enabled in your ini file");
13035 + array_init(return_value);
13036 + add_assoc_long(return_value, "num_slots", info->num_slots);
13037 + add_assoc_long(return_value, "ttl", info->ttl);
13038 + add_assoc_long(return_value, "num_hits", info->num_hits);
13039 + add_assoc_long(return_value, "num_misses", info->num_misses);
13040 + add_assoc_long(return_value, "start_time", info->start_time);
13041 + add_assoc_long(return_value, "expunges", info->expunges);
13042 + add_assoc_long(return_value, "mem_size", info->mem_size);
13043 + add_assoc_long(return_value, "num_entries", info->num_entries);
13044 + add_assoc_long(return_value, "num_inserts", info->num_inserts);
13045 +#ifdef MULTIPART_EVENT_FORMDATA
13046 + add_assoc_long(return_value, "file_upload_progress", 1);
13048 + add_assoc_long(return_value, "file_upload_progress", 0);
13051 + add_assoc_stringl(return_value, "memory_type", "mmap", sizeof("mmap")-1, 1);
13053 + add_assoc_stringl(return_value, "memory_type", "IPC shared", sizeof("IPC shared")-1, 1);
13056 + add_assoc_stringl(return_value, "locking_type", "IPC semaphore", sizeof("IPC semaphore")-1, 1);
13057 +#elif APC_FUTEX_LOCKS
13058 + add_assoc_stringl(return_value, "locking_type", "Linux Futex", sizeof("Linux Futex")-1, 1);
13059 +#elif APC_PTHREADMUTEX_LOCKS
13060 + add_assoc_stringl(return_value, "locking_type", "pthread mutex", sizeof("pthread mutex")-1, 1);
13061 +#elif APC_SPIN_LOCKS
13062 + add_assoc_stringl(return_value, "locking_type", "spin", sizeof("spin")-1, 1);
13064 + add_assoc_stringl(return_value, "locking_type", "file", sizeof("file")-1, 1);
13067 + apc_cache_free_info(info);
13071 + ALLOC_INIT_ZVAL(list);
13072 + array_init(list);
13074 + for (p = info->list; p != NULL; p = p->next) {
13077 + ALLOC_INIT_ZVAL(link);
13078 + array_init(link);
13080 + if(p->type == APC_CACHE_ENTRY_FILE) {
13081 + add_assoc_string(link, "filename", p->data.file.filename, 1);
13082 + add_assoc_long(link, "device", p->data.file.device);
13083 + add_assoc_long(link, "inode", p->data.file.inode);
13084 + add_assoc_string(link, "type", "file", 1);
13085 + } else if(p->type == APC_CACHE_ENTRY_USER) {
13086 + add_assoc_string(link, "info", p->data.user.info, 1);
13087 + add_assoc_long(link, "ttl", (long)p->data.user.ttl);
13088 + add_assoc_string(link, "type", "user", 1);
13090 + add_assoc_long(link, "num_hits", p->num_hits);
13091 + add_assoc_long(link, "mtime", p->mtime);
13092 + add_assoc_long(link, "creation_time", p->creation_time);
13093 + add_assoc_long(link, "deletion_time", p->deletion_time);
13094 + add_assoc_long(link, "access_time", p->access_time);
13095 + add_assoc_long(link, "ref_count", p->ref_count);
13096 + add_assoc_long(link, "mem_size", p->mem_size);
13097 + add_next_index_zval(list, link);
13099 + add_assoc_zval(return_value, "cache_list", list);
13101 + ALLOC_INIT_ZVAL(list);
13102 + array_init(list);
13104 + for (p = info->deleted_list; p != NULL; p = p->next) {
13107 + ALLOC_INIT_ZVAL(link);
13108 + array_init(link);
13110 + if(p->type == APC_CACHE_ENTRY_FILE) {
13111 + add_assoc_string(link, "filename", p->data.file.filename, 1);
13112 + add_assoc_long(link, "device", p->data.file.device);
13113 + add_assoc_long(link, "inode", p->data.file.inode);
13114 + add_assoc_string(link, "type", "file", 1);
13115 + } else if(p->type == APC_CACHE_ENTRY_USER) {
13116 + add_assoc_string(link, "info", p->data.user.info, 1);
13117 + add_assoc_long(link, "ttl", (long)p->data.user.ttl);
13118 + add_assoc_string(link, "type", "user", 1);
13120 + add_assoc_long(link, "num_hits", p->num_hits);
13121 + add_assoc_long(link, "mtime", p->mtime);
13122 + add_assoc_long(link, "creation_time", p->creation_time);
13123 + add_assoc_long(link, "deletion_time", p->deletion_time);
13124 + add_assoc_long(link, "access_time", p->access_time);
13125 + add_assoc_long(link, "ref_count", p->ref_count);
13126 + add_assoc_long(link, "mem_size", p->mem_size);
13127 + add_next_index_zval(list, link);
13129 + add_assoc_zval(return_value, "deleted_list", list);
13131 + apc_cache_free_info(info);
13135 +/* {{{ proto void apc_clear_cache() */
13136 +PHP_FUNCTION(apc_clear_cache)
13138 + char *cache_type;
13141 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &cache_type, &ct_len) == FAILURE) {
13145 + if(ZEND_NUM_ARGS()) {
13146 + if(!strcasecmp(cache_type,"user")) {
13147 + apc_cache_clear(apc_user_cache);
13151 + apc_cache_clear(apc_cache);
13155 +/* {{{ proto array apc_sma_info([bool limited]) */
13156 +PHP_FUNCTION(apc_sma_info)
13158 + apc_sma_info_t* info;
13159 + zval* block_lists;
13161 + zend_bool limited = 0;
13163 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &limited) == FAILURE) {
13167 + info = apc_sma_info(limited);
13170 + php_error_docref(NULL TSRMLS_CC, E_WARNING, "No APC SMA info available. Perhaps APC is disabled via apc.enabled?");
13174 + array_init(return_value);
13175 + add_assoc_long(return_value, "num_seg", info->num_seg);
13176 + add_assoc_long(return_value, "seg_size", info->seg_size);
13177 + add_assoc_long(return_value, "avail_mem", apc_sma_get_avail_mem());
13180 + apc_sma_free_info(info);
13184 +#if ALLOC_DISTRIBUTION
13186 + size_t *adist = apc_sma_get_alloc_distribution();
13188 + ALLOC_INIT_ZVAL(list);
13189 + array_init(list);
13190 + for(i=0; i<30; i++) {
13191 + add_next_index_long(list, adist[i]);
13193 + add_assoc_zval(return_value, "adist", list);
13196 + ALLOC_INIT_ZVAL(block_lists);
13197 + array_init(block_lists);
13199 + for (i = 0; i < info->num_seg; i++) {
13200 + apc_sma_link_t* p;
13203 + ALLOC_INIT_ZVAL(list);
13204 + array_init(list);
13206 + for (p = info->list[i]; p != NULL; p = p->next) {
13209 + ALLOC_INIT_ZVAL(link);
13210 + array_init(link);
13212 + add_assoc_long(link, "size", p->size);
13213 + add_assoc_long(link, "offset", p->offset);
13214 + add_next_index_zval(list, link);
13216 + add_next_index_zval(block_lists, list);
13218 + add_assoc_zval(return_value, "block_lists", block_lists);
13219 + apc_sma_free_info(info);
13223 +/* {{{ _apc_store */
13224 +int _apc_store(char *strkey, int strkey_len, const zval *val, const unsigned int ttl, const int exclusive TSRMLS_DC) {
13225 + apc_cache_entry_t *entry;
13226 + apc_cache_key_t key;
13228 + size_t mem_size = 0;
13230 +#if PHP_API_VERSION <= 20041225
13231 +#if HAVE_APACHE && defined(APC_PHP4_STAT)
13232 + t = ((request_rec *)SG(server_context))->request_time;
13237 + t = sapi_get_request_time(TSRMLS_C);
13240 + if(!APCG(enabled)) return 0;
13242 + HANDLE_BLOCK_INTERRUPTIONS();
13244 + APCG(mem_size_ptr) = &mem_size;
13245 + if (!(entry = apc_cache_make_user_entry(strkey, strkey_len + 1, val, ttl))) {
13246 + APCG(mem_size_ptr) = NULL;
13247 + apc_cache_expunge(apc_cache,t);
13248 + apc_cache_expunge(apc_user_cache,t);
13249 + HANDLE_UNBLOCK_INTERRUPTIONS();
13253 + if (!apc_cache_make_user_key(&key, strkey, strkey_len + 1, t)) {
13254 + APCG(mem_size_ptr) = NULL;
13255 + apc_cache_free_entry(entry);
13256 + apc_cache_expunge(apc_cache,t);
13257 + apc_cache_expunge(apc_user_cache,t);
13258 + HANDLE_UNBLOCK_INTERRUPTIONS();
13262 + if (!apc_cache_user_insert(apc_user_cache, key, entry, t, exclusive TSRMLS_CC)) {
13263 + APCG(mem_size_ptr) = NULL;
13264 + apc_cache_free_entry(entry);
13265 + apc_cache_expunge(apc_cache,t);
13266 + apc_cache_expunge(apc_user_cache,t);
13267 + HANDLE_UNBLOCK_INTERRUPTIONS();
13271 + APCG(mem_size_ptr) = NULL;
13273 + HANDLE_UNBLOCK_INTERRUPTIONS();
13279 +/* {{{ proto int apc_store(string key, zval var [, ttl ])
13281 +PHP_FUNCTION(apc_store) {
13287 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|l", &strkey, &strkey_len, &val, &ttl) == FAILURE) {
13291 + if(!strkey_len) RETURN_FALSE;
13293 + if(_apc_store(strkey, strkey_len, val, (unsigned int)ttl, 0 TSRMLS_CC)) RETURN_TRUE;
13298 +/* {{{ proto int apc_add(string key, zval var [, ttl ])
13300 +PHP_FUNCTION(apc_add) {
13306 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|l", &strkey, &strkey_len, &val, &ttl) == FAILURE) {
13310 + if(!strkey_len) RETURN_FALSE;
13312 + if(_apc_store(strkey, strkey_len, val, (unsigned int)ttl, 1 TSRMLS_CC)) RETURN_TRUE;
13317 +void *apc_erealloc_wrapper(void *ptr, size_t size) {
13318 + return _erealloc(ptr, size, 0 ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
13321 +/* {{{ RETURN_ZVAL for php4 */
13322 +#if !defined(ZEND_ENGINE_2) && !defined(RETURN_ZVAL)
13323 +#define RETURN_ZVAL(zv, copy, dtor) { RETVAL_ZVAL(zv, copy, dtor); return; }
13324 +#define RETVAL_ZVAL(zv, copy, dtor) ZVAL_ZVAL(return_value, zv, copy, dtor)
13325 +#define ZVAL_ZVAL(z, zv, copy, dtor) { \
13326 + int is_ref, refcount; \
13327 + is_ref = (z)->is_ref; \
13328 + refcount = (z)->refcount; \
13331 + zval_copy_ctor(z); \
13337 + zval_ptr_dtor(&zv); \
13339 + (z)->is_ref = is_ref; \
13340 + (z)->refcount = refcount; \
13345 +/* {{{ proto mixed apc_fetch(mixed key)
13347 +PHP_FUNCTION(apc_fetch) {
13350 + HashPosition hpos;
13353 + zval *result_entry;
13356 + apc_cache_entry_t* entry;
13359 + if(!APCG(enabled)) RETURN_FALSE;
13361 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &key) == FAILURE) {
13365 +#if PHP_API_VERSION <= 20041225
13366 +#if HAVE_APACHE && defined(APC_PHP4_STAT)
13367 + t = ((request_rec *)SG(server_context))->request_time;
13372 + t = sapi_get_request_time(TSRMLS_C);
13375 + if(Z_TYPE_P(key) != IS_STRING && Z_TYPE_P(key) != IS_ARRAY) {
13376 + convert_to_string(key);
13379 + if(Z_TYPE_P(key) == IS_STRING) {
13380 + strkey = Z_STRVAL_P(key);
13381 + strkey_len = Z_STRLEN_P(key);
13382 + if(!strkey_len) RETURN_FALSE;
13383 + entry = apc_cache_user_find(apc_user_cache, strkey, strkey_len + 1, t);
13385 + /* deep-copy returned shm zval to emalloc'ed return_value */
13386 + apc_cache_fetch_zval(return_value, entry->data.user.val, apc_php_malloc, apc_php_free);
13387 + apc_cache_release(apc_user_cache, entry);
13391 + } else if(Z_TYPE_P(key) == IS_ARRAY) {
13392 + hash = Z_ARRVAL_P(key);
13393 + MAKE_STD_ZVAL(result);
13394 + array_init(result);
13395 + zend_hash_internal_pointer_reset_ex(hash, &hpos);
13396 + while(zend_hash_get_current_data_ex(hash, (void**)&hentry, &hpos) == SUCCESS) {
13397 + if(Z_TYPE_PP(hentry) != IS_STRING) {
13398 + apc_wprint("apc_fetch() expects a string or array of strings.");
13401 + entry = apc_cache_user_find(apc_user_cache, Z_STRVAL_PP(hentry), Z_STRLEN_PP(hentry) + 1, t);
13403 + /* deep-copy returned shm zval to emalloc'ed return_value */
13404 + MAKE_STD_ZVAL(result_entry);
13405 + apc_cache_fetch_zval(result_entry, entry->data.user.val, apc_php_malloc, apc_php_free);
13406 + apc_cache_release(apc_user_cache, entry);
13407 + zend_hash_add(Z_ARRVAL_P(result), Z_STRVAL_PP(hentry), Z_STRLEN_PP(hentry) +1, &result_entry, sizeof(zval*), NULL);
13408 + } /* don't set values we didn't find */
13409 + zend_hash_move_forward_ex(hash, &hpos);
13411 + RETURN_ZVAL(result, 0, 1);
13413 + apc_wprint("apc_fetch() expects a string or array of strings.");
13421 +/* {{{ proto mixed apc_delete(string key)
13423 +PHP_FUNCTION(apc_delete) {
13427 + if(!APCG(enabled)) RETURN_FALSE;
13429 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &strkey, &strkey_len) == FAILURE) {
13433 + if(!strkey_len) RETURN_FALSE;
13435 + if(apc_cache_user_delete(apc_user_cache, strkey, strkey_len + 1)) {
13443 +static void _apc_define_constants(zval *constants, zend_bool case_sensitive TSRMLS_DC) {
13445 + unsigned int const_key_len;
13447 + HashPosition pos;
13449 + zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(constants), &pos);
13450 + while (zend_hash_get_current_data_ex(Z_ARRVAL_P(constants), (void**)&entry, &pos) == SUCCESS) {
13455 + key_type = zend_hash_get_current_key_ex(Z_ARRVAL_P(constants), &const_key, &const_key_len, &num_key, 0, &pos);
13456 + if(key_type != HASH_KEY_IS_STRING) {
13457 + zend_hash_move_forward_ex(Z_ARRVAL_P(constants), &pos);
13460 + switch(Z_TYPE_PP(entry)) {
13465 + case IS_RESOURCE:
13469 + zend_hash_move_forward_ex(Z_ARRVAL_P(constants), &pos);
13472 + c.value = **entry;
13473 + zval_copy_ctor(&c.value);
13474 + c.flags = case_sensitive;
13475 + c.name = zend_strndup(const_key, const_key_len);
13476 + c.name_len = const_key_len;
13477 +#ifdef ZEND_ENGINE_2
13478 + c.module_number = PHP_USER_CONSTANT;
13480 + zend_register_constant(&c TSRMLS_CC);
13482 + zend_hash_move_forward_ex(Z_ARRVAL_P(constants), &pos);
13486 +/* {{{ proto mixed apc_define_constants(string key, array constants [,bool case-sensitive])
13488 +PHP_FUNCTION(apc_define_constants) {
13491 + zval *constants = NULL;
13492 + zend_bool case_sensitive = 1;
13493 + int argc = ZEND_NUM_ARGS();
13495 + if (zend_parse_parameters(argc TSRMLS_CC, "sa|b", &strkey, &strkey_len, &constants, &case_sensitive) == FAILURE) {
13499 + if(!strkey_len) RETURN_FALSE;
13501 + _apc_define_constants(constants, case_sensitive TSRMLS_CC);
13502 + if(_apc_store(strkey, strkey_len, constants, 0, 0 TSRMLS_CC)) RETURN_TRUE;
13506 +/* {{{ proto mixed apc_load_constants(string key [, bool case-sensitive])
13508 +PHP_FUNCTION(apc_load_constants) {
13511 + apc_cache_entry_t* entry;
13513 + zend_bool case_sensitive = 1;
13515 + if(!APCG(enabled)) RETURN_FALSE;
13516 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &strkey, &strkey_len, &case_sensitive) == FAILURE) {
13520 + if(!strkey_len) RETURN_FALSE;
13522 +#if PHP_API_VERSION <= 20041225
13523 +#if HAVE_APACHE && defined(APC_PHP4_STAT)
13524 + t = ((request_rec *)SG(server_context))->request_time;
13529 + t = sapi_get_request_time(TSRMLS_C);
13532 + entry = apc_cache_user_find(apc_user_cache, strkey, strkey_len + 1, t);
13535 + _apc_define_constants(entry->data.user.val, case_sensitive TSRMLS_CC);
13536 + apc_cache_release(apc_user_cache, entry);
13544 +/* {{{ proto boolean apc_compile_file(string filename)
13546 +PHP_FUNCTION(apc_compile_file) {
13548 + int filename_len;
13549 + zend_file_handle file_handle;
13550 + zend_op_array *op_array;
13551 + long slam_defense = 0;
13552 + char** filters = NULL;
13553 + zend_bool cache_by_default = 1;
13554 + HashTable cg_function_table, cg_class_table, eg_function_table, eg_class_table;
13555 + HashTable *cg_orig_function_table, *cg_orig_class_table, *eg_orig_function_table, *eg_orig_class_table;
13557 + if(!APCG(enabled)) RETURN_FALSE;
13559 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) {
13563 + if(!filename) RETURN_FALSE;
13565 + /* If slam defense is active, temporarily disable */
13566 + if(APCG(slam_defense)) {
13567 + slam_defense = APCG(slam_defense);
13568 + APCG(slam_defense) = 0;
13571 + /* If filter is active, temporarily disable */
13572 + if(APCG(filters) != NULL) {
13573 + filters = APCG(filters);
13574 + APCG(filters) = NULL;
13577 + /* If cache_by_default is off, temporarily enable */
13578 + if(!APCG(cache_by_default)) {
13579 + cache_by_default = APCG(cache_by_default);
13580 + APCG(cache_by_default) = 1;
13583 + /* Replace function/class tables to avoid namespace conflicts */
13584 + zend_hash_init_ex(&cg_function_table, 100, NULL, ZEND_FUNCTION_DTOR, 1, 0);
13585 + cg_orig_function_table = CG(function_table);
13586 + CG(function_table) = &cg_function_table;
13587 + zend_hash_init_ex(&cg_class_table, 10, NULL, ZEND_CLASS_DTOR, 1, 0);
13588 + cg_orig_class_table = CG(class_table);
13589 + CG(class_table) = &cg_class_table;
13590 + zend_hash_init_ex(&eg_function_table, 100, NULL, ZEND_FUNCTION_DTOR, 1, 0);
13591 + eg_orig_function_table = EG(function_table);
13592 + EG(function_table) = &eg_function_table;
13593 + zend_hash_init_ex(&eg_class_table, 10, NULL, ZEND_CLASS_DTOR, 1, 0);
13594 + eg_orig_class_table = EG(class_table);
13595 + EG(class_table) = &eg_class_table;
13597 + /* Compile the file, loading it into the cache */
13598 + file_handle.type = ZEND_HANDLE_FILENAME;
13599 + file_handle.filename = filename;
13600 + file_handle.free_filename = 0;
13601 + file_handle.opened_path = NULL;
13603 + op_array = zend_compile_file(&file_handle, ZEND_INCLUDE TSRMLS_CC);
13605 + apc_eprint("Error compiling %s in apc_compile_file.", filename);
13607 + } zend_end_try();
13609 + /* Return class/function tables to previous states, destroy temp tables */
13610 + CG(function_table) = cg_orig_function_table;
13611 + zend_hash_destroy(&cg_function_table);
13612 + CG(class_table) = cg_orig_class_table;
13613 + zend_hash_destroy(&cg_class_table);
13614 + EG(function_table) = eg_orig_function_table;
13615 + zend_hash_destroy(&eg_function_table);
13616 + EG(class_table) = eg_orig_class_table;
13617 + zend_hash_destroy(&eg_class_table);
13619 + /* Restore global settings */
13620 + APCG(slam_defense) = slam_defense;
13621 + APCG(filters) = filters;
13622 + APCG(cache_by_default) = cache_by_default;
13624 + if(op_array == NULL) { RETURN_FALSE; }
13626 + /* Free up everything */
13627 + zend_destroy_file_handle(&file_handle TSRMLS_CC);
13628 +#ifdef ZEND_ENGINE_2
13629 + destroy_op_array(op_array TSRMLS_CC);
13631 + destroy_op_array(op_array);
13639 +/* {{{ apc_functions[] */
13640 +function_entry apc_functions[] = {
13641 + PHP_FE(apc_cache_info, NULL)
13642 + PHP_FE(apc_clear_cache, NULL)
13643 + PHP_FE(apc_sma_info, NULL)
13644 + PHP_FE(apc_store, NULL)
13645 + PHP_FE(apc_fetch, NULL)
13646 + PHP_FE(apc_delete, NULL)
13647 + PHP_FE(apc_define_constants, NULL)
13648 + PHP_FE(apc_load_constants, NULL)
13649 + PHP_FE(apc_compile_file, NULL)
13650 + {NULL, NULL, NULL}
13654 +/* {{{ module definition structure */
13656 +zend_module_entry apc_module_entry = {
13657 + STANDARD_MODULE_HEADER,
13661 + PHP_MSHUTDOWN(apc),
13663 + PHP_RSHUTDOWN(apc),
13666 + STANDARD_MODULE_PROPERTIES
13669 +#ifdef COMPILE_DL_APC
13670 +ZEND_GET_MODULE(apc)
13675 + * Local variables:
13677 + * c-basic-offset: 4
13679 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
13680 + * vim<600: expandtab sw=4 ts=4 sts=4
13682 diff -ruN php-5.1.6.old/ext/apc/php_apc.h php-5.1.6/ext/APC/php_apc.h
13683 --- php-5.1.6.old/ext/apc/php_apc.h 1969-12-31 18:00:00.000000000 -0600
13684 +++ php-5.1.6/ext/apc/php_apc.h 2007-04-02 18:05:30.000000000 -0500
13687 + +----------------------------------------------------------------------+
13689 + +----------------------------------------------------------------------+
13690 + | Copyright (c) 2006 The PHP Group |
13691 + +----------------------------------------------------------------------+
13692 + | This source file is subject to version 3.01 of the PHP license, |
13693 + | that is bundled with this package in the file LICENSE, and is |
13694 + | available through the world-wide-web at the following url: |
13695 + | http://www.php.net/license/3_01.txt |
13696 + | If you did not receive a copy of the PHP license and are unable to |
13697 + | obtain it through the world-wide-web, please send a note to |
13698 + | license@php.net so we can mail you a copy immediately. |
13699 + +----------------------------------------------------------------------+
13700 + | Authors: Daniel Cowgill <dcowgill@communityconnect.com> |
13701 + | George Schlossnagle <george@omniti.com> |
13702 + | Rasmus Lerdorf <rasmus@php.net> |
13703 + +----------------------------------------------------------------------+
13705 + This software was contributed to PHP by Community Connect Inc. in 2002
13706 + and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
13707 + Future revisions and derivatives of this source code must acknowledge
13708 + Community Connect Inc. as the original contributor of this module by
13709 + leaving this note intact in the source code.
13711 + All other licensing and usage conditions are those of the PHP Group.
13715 +/* $Id: php_apc.h,v 3.14 2006/03/12 00:31:45 rasmus Exp $ */
13720 +#include "apc_php.h"
13721 +#include "apc_globals.h"
13723 +extern zend_module_entry apc_module_entry;
13724 +#define apc_module_ptr &apc_module_entry
13726 +#define phpext_apc_ptr apc_module_ptr
13728 +#endif /* PHP_APC_H */
13731 + * Local variables:
13733 + * c-basic-offset: 4
13735 + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
13736 + * vim<600: expandtab sw=4 ts=4 sts=4
13738 diff -ruN php-5.1.6.old/ext/apc/TECHNOTES.txt php-5.1.6/ext/APC/TECHNOTES.txt
13739 --- php-5.1.6.old/ext/apc/TECHNOTES.txt 1969-12-31 18:00:00.000000000 -0600
13740 +++ php-5.1.6/ext/apc/TECHNOTES.txt 2007-04-02 18:05:30.000000000 -0500
13742 +APC Quick-Start Braindump
13744 +This is a rapidly written braindump of how APC currently works in the
13745 +form of a quick-start guide to start hacking on APC.
13747 +1. Install and use APC a bit so you know what it does from the end-user's
13749 + user-space functions are all explained here:
13751 +2. Grab the current APC code from CVS:
13753 + cvs -d:pserver:cvsread@cvs.php.net:/repository login
13755 + cvs -d:pserver:cvsread@cvs.php.net:/repository co pecl/apc
13757 + apc/php_apc.c has most of the code for the user-visible stuff. It is
13758 + also a regular PHP extension in the sense that there are MINIT, MINFO,
13759 + MSHUTDOWN, RSHUTDOWN, etc. functions.
13765 + ./configure --enable-apc --enable-mmap
13767 + cp modules/apc.so /usr/local/lib/php
13768 + apachectl restart
13770 +4. Debugging Hints
13773 + gdb /usr/bin/httpd
13777 + Grab the .gdbinit from the PHP source tree and have a look at the macros.
13779 +5. Look through apc/apc_sma.c
13780 + It is a pretty standard memory allocator.
13782 + apc_sma_malloc, apc_sma_realloc, apc_sma_strdup and apc_sma_free behave to the
13783 + caller just like malloc, realloc, strdup and free
13785 + On server startup the MINIT hook in php_apc.c calls apc_module_init() in
13786 + apc_main.c which in turn calls apc_sma_init(). apc_sma_init calls into
13787 + apc_mmap.c to mmap the specified sized segment (I tend to just use a single
13788 + segment). apc_mmap.c should be self-explanatory. It mmaps a temp file and
13789 + then unlinks that file right after the mmap to provide automatic shared memory
13790 + cleanup in case the process dies.
13792 + Once the region has been initialized we stick a header_t at the beginning
13793 + of the region. It contains the total size in header->segsize and the number
13794 + of bytes available in header->avail.
13796 + After the header comes a bit of a hack. A zero-sized block is inserted just
13797 + to make things easier later on. And then a huge block that is basically
13798 + the size of the entire segment minus the two (for the 0-sized block, and this one)
13801 + The code for this is:
13803 + header = (header_t*) shmaddr;
13804 + header->segsize = sma_segsize;
13805 + header->avail = sma_segsize - sizeof(header_t) - sizeof(block_t) - alignword(sizeof(int));
13806 + memset(&header->lock,0,sizeof(header->lock));
13807 + sma_lock = &header->lock;
13808 + block = BLOCKAT(sizeof(header_t));
13810 + block->next = sizeof(header_t) + sizeof(block_t);
13811 + block = BLOCKAT(block->next);
13812 + block->size = header->avail;
13815 + So the shared memory looks like this:
13817 + +--------+-------+---------------------------------+
13818 + | header | block | block |
13819 + +--------+-------+---------------------------------+
13821 + sma_shmaddrs[0] gives you the address of header
13823 + The blocks are just a simple offset-based linked list (so no pointers):
13825 + typedef struct block_t block_t;
13827 + int size; /* size of this block */
13828 + int next; /* offset in segment of next free block */
13831 + The BLOCKAT macro turns an offset into an actual address for you:
13833 + #define BLOCKAT(offset) ((block_t*)((char *)shmaddr + offset))
13835 + where shmaddr = sma_shaddrs[0]
13837 + And the OFFSET macro goes the other way:
13839 + #define OFFSET(block) ((int)(((char*)block) - (char*)shmaddr))
13841 + Allocating a block with a call to apc_sma_allocate() walks through the
13842 + linked list of blocks until it finds one that is >= to the requested size.
13843 + The first call to apc_sma_allocate() will hit the second block. We then
13844 + chop up that block so it looks like this:
13846 + +--------+-------+-------+-------------------------+
13847 + | header | block | block | block |
13848 + +--------+-------+-------+-------------------------+
13850 + Then we unlink that block from the linked list so it won't show up
13851 + as an available block on the next allocate. So we actually have:
13853 + +--------+-------+ +-------------------------+
13854 + | header | block |------>| block |
13855 + +--------+-------+ +-------------------------+
13857 + And header->avail along with block->size of the remaining large
13858 + block are updated accordingly. The arrow there representing the
13859 + link which now points to a block with an offset further along in
13862 + When the block is freed using apc_sma_deallocate() the steps are
13863 + basically just reversed. The block is put back and then the deallocate
13864 + code looks at the block before and after to see if the block immediately
13865 + before and after are free and if so the blocks are combined. So you never
13866 + have 2 free blocks next to each other, apart from at the front with that
13867 + 0-sized dummy block. This mostly prevents fragmentation. I have been
13868 + toying with the idea of always allocating block at 2^n boundaries to make
13869 + it more likely that they will be re-used to cut down on fragmentation further.
13870 + That's what the POWER_OF_TWO_BLOCKSIZE you see in apc_sma.c is all about.
13872 + Of course, anytime we fiddle with our shared memory segment we lock using
13873 + the locking macros, LOCK() and UNLOCK().
13875 + That should mostly take care of the low-level shared memory handling.
13877 +6. Next up is apc_main.c and apc_cache.c which implement the meat of the
13880 + The apc_main.c file mostly calls functions in apc_sma.c to allocate memory
13881 + and apc_cache.c for actual cache manipulation.
13883 + After the shared memory segment is created and the caches are initialized,
13884 + apc_module_init() installs the my_compile_file() function overriding Zend's
13885 + version. I'll talk about my_compile_file() and the rest of apc_compile.c
13886 + in the next section. For now I will stick with apc_main.c and apc_cache.c
13887 + and talk about the actual caches. A cache consists of a block of shared
13888 + memory returned by apc_sma_allocate() via apc_sma_malloc(). You will
13889 + notice references to apc_emalloc(). apc_emalloc() is just a thin wrapper
13890 + around PHP's own emalloc() function which allocates per-process memory from
13891 + PHP's pool-based memory allocator. Don't confuse apc_emalloc() and
13892 + apc_sma_malloc() as the first is per-process and the second is shared memory.
13894 + The cache is stored in/described by this struct allocated locally using
13897 + struct apc_cache_t {
13898 + void* shmaddr; /* process (local) address of shared cache */
13899 + header_t* header; /* cache header (stored in SHM) */
13900 + slot_t** slots; /* array of cache slots (stored in SHM) */
13901 + int num_slots; /* number of slots in cache */
13902 + int gc_ttl; /* maximum time on GC list for a slot */
13903 + int ttl; /* if slot is needed and entry's access time is older than this ttl, remove it */
13906 + Whenever you see functions that take a 'cache' argument, this is what they
13907 + take. And apc_cache_create() returns a pointer to this populated struct.
13909 + At the beginning of the cache we have a header. Remember, we are down a level now
13910 + from the sma stuff. The sma stuff is the low-level shared-memory allocator which
13911 + has its own header which is completely separate and invisible to apc_cache.c.
13912 + As far as apc_cache.c is concerned the block of memory it is working with could
13913 + have come from a call to malloc().
13915 + The header looks like this:
13917 + typedef struct header_t header_t;
13918 + struct header_t {
13919 + int num_hits; /* total successful hits in cache */
13920 + int num_misses; /* total unsuccessful hits in cache */
13921 + slot_t* deleted_list; /* linked list of to-be-deleted slots */
13924 + Since this is at the start of the shared memory segment, these values are accessible
13925 + across all the yapache processes and hence access to them has to be locked.
13927 + After the header we have an array of slots. The number of slots is user-defined
13928 + through the apc.num_slots ini hint. Each slot is described by:
13930 + typedef struct slot_t slot_t;
13932 + apc_cache_key_t key; /* slot key */
13933 + apc_cache_entry_t* value; /* slot value */
13934 + slot_t* next; /* next slot in linked list */
13935 + int num_hits; /* number of hits to this bucket */
13936 + time_t creation_time; /* time slot was initialized */
13937 + time_t deletion_time; /* time slot was removed from cache */
13938 + time_t access_time; /* time slot was last accessed */
13941 + The slot_t *next there is a linked list to other slots that happened to hash to the
13942 + same array position.
13944 + apc_cache_insert() shows what happens on a new cache insert.
13946 + slot = &cache->slots[hash(key) % cache->num_slots];
13948 + cache->slots is our array of slots in the segment. hash() is simply:
13950 + static unsigned int hash(apc_cache_key_t key)
13952 + return key.data.file.device + key.data.file.inode;
13955 + That is, we use the file's device and inode to uniquely identify it. Initially
13956 + we had used the file's full path, but getting that requires a realpath() call which
13957 + is amazingly expensive since it has to stat each component of the path to resolve
13958 + symlinks and get rid of relative path components. By using the device+inode we
13959 + can uniquely identify a file with a single stat.
13961 + So, on an insert we find the array position in the slots array by hasing the device+inode.
13962 + If there are currently no other slots there, we just create the slot and stick it into
13965 + *slot = make_slot(key, value, *slot, t)
13967 + If there are other slots already at this position we walk the link list to get to
13968 + the end. Here is the loop:
13971 + if (key_equals((*slot)->key.data.file, key.data.file)) {
13972 + /* If existing slot for the same device+inode is different, remove it and insert the new version */
13973 + if ((*slot)->key.mtime != key.mtime) {
13974 + remove_slot(cache, slot);
13979 + } else if(cache->ttl && (*slot)->access_time < (t - cache->ttl)) {
13980 + remove_slot(cache, slot);
13983 + slot = &(*slot)->next;
13986 + That first key_equals() check sees if we have an exact match meaning the file
13987 + is already in the cache. Since we try to find the file in the cache before doing
13988 + an insert, this will generally only happen if another process managed to beat us
13989 + to inserting it. If we have a newer version of the file at this point we remove
13990 + it an insert the new version. If our version is not newer we just return without
13993 + While walking the linked list we also check to see if the cache has a TTL defined.
13994 + If while walking the linked list we see a slot that has expired, we remove it
13995 + since we are right there looking at it. This is the only place we remove stale
13996 + entries unless the shared memory segment fills up and we force a full expunge via
13997 + apc_cache_expunge(). apc_cache_expunge() walks the entire slots array and walks
13998 + down every linked list removing stale slots to free up room. This is obviously
13999 + slow and thus only happens when we have run out of room.
14001 + apc_cache_find() simply hashes and returns the entry if it is there. If it is there
14002 + but older than the mtime in the entry we are looking for, we delete the one that is
14003 + there and return indicating we didn't find it.
14005 + Next we need to understand what an actual cache entry looks like. Have a look at
14006 + apc_cache.h for the structs. I sort of glossed over the key part earlier saying
14007 + that we just used the device+inode to find a hash slot. It is actually a bit more
14008 + complex than that because we have two kinds of caches. We have the standard file
14009 + cache containing opcode arrays, but we also have a user-controlled cache that the
14010 + user can insert whatever they want into via apc_store(). For the user cache we
14011 + obviously don't have a device+inode. The actual identifier is provided by the user
14012 + as a char *. So the key is actually a union that looks like this:
14014 + typedef union _apc_cache_key_data_t {
14016 + int device; /* the filesystem device */
14017 + int inode; /* the filesystem inode */
14020 + char *identifier;
14022 + } apc_cache_key_data_t;
14024 + struct apc_cache_key_t {
14025 + apc_cache_key_data_t data;
14026 + int mtime; /* the mtime of this cached entry */
14029 + And we have two sets of functions to do inserts and finds. apc_cache_user_find()
14030 + and apc_cache_user_insert() operate on the user cache.
14032 + Ok, on to the actual cache entry. Again, because we have two kinds of caches, we
14033 + also have the corresponding two kinds of cache entries described by this union:
14035 + typedef union _apc_cache_entry_value_t {
14037 + char *filename; /* absolute path to source file */
14038 + zend_op_array* op_array; /* op_array allocated in shared memory */
14039 + apc_function_t* functions; /* array of apc_function_t's */
14040 + apc_class_t* classes; /* array of apc_class_t's */
14045 + unsigned int ttl;
14047 + } apc_cache_entry_value_t;
14049 + And then the actual cache entry:
14051 + struct apc_cache_entry_t {
14052 + apc_cache_entry_value_t data;
14053 + unsigned char type;
14057 + The user entry is pretty simple and not all that important for now. I will
14058 + concentrate on the file entries since that is what holds the actual compiled
14059 + opcode arrays along with the functions and classes required by the executor.
14061 + apc_cache_make_file_entry() in apc_cache.c shows how an entry is constructed.
14062 + The main thing to understand here is that we need more than just the opcode
14063 + array, we also need the functions and classes created by the compiler when it
14064 + created the opcode array. As far as the executor is concerned, it doesn't know
14065 + that it isn't operating in normal mode being called right after the parse/compile
14066 + phase, so we need to recreate everything so it looks exactly like it would at
14069 +7. my_compile_file() and apc_compile.c
14071 + my_compile_file() in apc_main.c controls where we get the opcodes from. If
14072 + the user-specified filters exclude the file from being cached, then we just
14073 + call the original compile function and return. Otherwise we fetch the request
14074 + time from Apache to avoid an extra syscall, create the key so we can look up
14075 + the file in the cache. If we find it we stick it on a local stack which we
14076 + use at cleanup time to make sure we return everything back to normal after a
14077 + request and call cached_compile() which installs the functions and classes
14078 + associated with the op_array in this entry and then copy the op_array down
14079 + into our memory space for execution.
14081 + If we didn't find the file in the cache, we need to compile it and insert it.
14082 + To compile it we simply call the original compile function:
14084 + op_array = old_compile_file(h, type TSRMLS_CC);
14086 + To do the insert we need to copy the functions, classes and the opcode array
14087 + the compile phase created into shared memory. This all happens in apc_compile.c
14088 + in the apc_copy_op_array(), apc_copy_new_functions() and apc_copy_new_classes()
14089 + functions. Then we make the file entry and do the insert. Both of these
14090 + operations were described in the previous section.
14094 + The optimizer has been deprecated.
14096 +If you made it to the end of this, you should have a pretty good idea of where things are in
14097 +the code. I skimmed over a lot of things, so plan on spending some time reading through the code.
14099 diff -ruN php-5.1.6.old/ext/apc/tests/apc_001.phpt php-5.1.6/ext/APC/tests/apc_001.phpt
14100 --- php-5.1.6.old/ext/apc/tests/apc_001.phpt 1969-12-31 18:00:00.000000000 -0600
14101 +++ php-5.1.6/ext/apc/tests/apc_001.phpt 2007-04-02 18:05:30.000000000 -0500
14104 +APC: apc_store/fetch with strings
14106 +<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
14110 +apc.file_update_protection=0
14114 +$foo = 'hello world';
14116 +apc_store('foo',$foo);
14117 +$bar = apc_fetch('foo');
14126 +string(11) "hello world"
14127 +string(11) "hello world"
14130 diff -ruN php-5.1.6.old/ext/apc/tests/apc_002.phpt php-5.1.6/ext/APC/tests/apc_002.phpt
14131 --- php-5.1.6.old/ext/apc/tests/apc_002.phpt 1969-12-31 18:00:00.000000000 -0600
14132 +++ php-5.1.6/ext/apc/tests/apc_002.phpt 2007-04-02 18:05:30.000000000 -0500
14135 +APC: apc_store/fetch with objects
14137 +<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
14141 +apc.file_update_protection=0
14148 +apc_store('foo',$foo);
14150 +$bar = apc_fetch('foo');
14159 +object(foo)#%d (0) {
14161 +object(foo)#%d (0) {
14163 +object(foo)#%d (1) {
14168 diff -ruN php-5.1.6.old/ext/apc/tests/apc_003.phpt php-5.1.6/ext/APC/tests/apc_003.phpt
14169 --- php-5.1.6.old/ext/apc/tests/apc_003.phpt 1969-12-31 18:00:00.000000000 -0600
14170 +++ php-5.1.6/ext/apc/tests/apc_003.phpt 2007-04-02 18:05:30.000000000 -0500
14173 +APC: apc_store/fetch with objects
14175 +<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
14179 +apc.file_update_protection=0
14186 +apc_store('foo',$foo);
14188 +$bar = apc_fetch('foo');
14193 +class bar extends foo
14195 + public $pub = 'bar';
14196 + protected $pro = 'bar';
14197 + private $pri = 'bar'; // we don't see this, we'd need php 5.1 new serialization
14199 + function __construct()
14201 + $this->bar = true;
14204 + function change()
14206 + $this->pri = 'mod';
14210 +class baz extends bar
14212 + private $pri = 'baz';
14214 + function __construct()
14216 + parent::__construct();
14217 + $this->baz = true;
14225 +apc_store('baz', $baz);
14227 +var_dump(apc_fetch('baz'));
14233 +object(foo)#%d (0) {
14235 +object(foo)#%d (0) {
14237 +object(foo)#%d (1) {
14241 +object(baz)#%d (6) {
14242 + ["pri:private"]=>
14246 + ["pro:protected"]=>
14248 + ["pri:private"]=>
14255 +object(baz)#%d (6) {
14256 + ["pri:private"]=>
14260 + ["pro:protected"]=>
14262 + ["pri:private"]=>
14269 +object(baz)#%d (6) {
14270 + ["pri:private"]=>
14274 + ["pro:protected"]=>
14276 + ["pri:private"]=>
14284 diff -ruN php-5.1.6.old/ext/apc/tests/skipif.inc php-5.1.6/ext/APC/tests/skipif.inc
14285 --- php-5.1.6.old/ext/apc/tests/skipif.inc 1969-12-31 18:00:00.000000000 -0600
14286 +++ php-5.1.6/ext/apc/tests/skipif.inc 2007-04-02 18:05:30.000000000 -0500
14290 +if (!extension_loaded("apc")) die("skip");
14291 +//if (!ini_get('apc.enabled')) die("skip apc not enabled");
14294 diff -ruN php-5.1.6.old/ext/apc/TODO php-5.1.6/ext/APC/TODO
14295 --- php-5.1.6.old/ext/apc/TODO 1969-12-31 18:00:00.000000000 -0600
14296 +++ php-5.1.6/ext/apc/TODO 2007-04-02 18:05:30.000000000 -0500
14300 +1. Gallery2 doesn't work with PHP5+APC. There is something wrong
14301 + with the way methods are restored in some edge case I haven't
14302 + been able to figure out yet.
14303 + To reproduce install gallery2 and click down to an individual photo.
14305 +2. apc_store() probably needs some checks to skip trying to store
14306 + internal classes. Something along the lines of:
14308 + if(Z_TYPE_P(val) == IS_OBJECT) {
14309 + zend_class_entry *ce = Z_OBJCE_P(val);
14310 + if(ce->type == ZEND_INTERNAL_CLASS) {
14311 + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot cache internal objects");
14316 + in the apc_store() function in php_apc.c but I am wondering if it needs to do more
14321 +1. Some faster platform-specific locking mechanisms wouldd be nice. futex support
14322 + for the 2.6 Linux kernels, and/or x86-specific spinlock support.
14324 +2. The optimizer needs a lot of work.
14326 +3. Assert() elimination in the optimizer when some debug flag somewhere isn't set.