diff -ur allegro-4.2.0.orig/src/i386/icsprite.c allegro-4.2.0/src/i386/icsprite.c --- allegro-4.2.0.orig/src/i386/icsprite.c 2001-11-06 16:30:47.000000000 +0100 +++ allegro-4.2.0/src/i386/icsprite.c 2006-03-13 23:26:53.000000000 +0100 @@ -45,6 +45,11 @@ #if defined ALLEGRO_COLOR24 || defined ALLEGRO_COLOR32 unsigned long *p32; #endif + + #ifdef USE_MMAP_GEN_CODE_BUF + /* make sure we get a new map */ + _map_size = 0; + #endif for (y=0; yh; y++) { @@ -270,13 +275,40 @@ COMPILER_RET(); + #ifdef USE_MMAP_GEN_CODE_BUF + /* Lie about the size, return the size mapped which >= size used / + compiler_pos, because we need the size mapped for munmap */ + *len = _map_size; + /* we don't need _rw_map or _map_fd anymore */ + munmap(_rw_map, _map_size); + close(_map_fd); + return _exec_map; + #else p = malloc(compiler_pos); if (p) { memcpy(p, _scratch_mem, compiler_pos); *len = compiler_pos; + #ifdef ALLEGRO_WINDOWS + { + DWORD old_protect; + /* Play nice with Windows executable memory protection */ + VirtualProtect(p, compiler_pos, PAGE_EXECUTE_READWRITE, &old_protect); + } + #elif defined(HAVE_MPROTECT) + { + char *aligned_p = (char *)((unsigned long)p & ~(PAGE_SIZE-1ul)); + if (mprotect(aligned_p, compiler_pos + ((char *)p - aligned_p), + PROT_EXEC|PROT_READ|PROT_WRITE)) { + perror("allegro-error: mprotect failed during stretched blit!"); + free(p); + return NULL; + } + } + #endif } return p; + #endif } @@ -327,8 +359,11 @@ if (sprite) { for (plane=0; plane<4; plane++) if (sprite->proc[plane].draw) + #ifdef USE_MMAP_GEN_CODE_BUF + munmap(sprite->proc[plane].draw, sprite->proc[plane].len); + #else free(sprite->proc[plane].draw); - + #endif free(sprite); } } diff -ur allegro-4.2.0.orig/src/i386/istretch.c allegro-4.2.0/src/i386/istretch.c --- allegro-4.2.0.orig/src/i386/istretch.c 2006-03-13 22:48:45.000000000 +0100 +++ allegro-4.2.0/src/i386/istretch.c 2006-03-13 23:18:56.000000000 +0100 @@ -216,29 +216,18 @@ char depth; char flags; int lru; - void *data; + void *exec; /* xr_ mapping in the mmap case, normally both in one. */ int size; +#ifdef USE_MMAP_GEN_CODE_BUF + void *rw; /* _rw mapping for the mmap case. */ + int fd; /* mapping backing fd for the mmap case. */ +#endif } STRETCHER_INFO; - #define NUM_STRETCHERS 8 - -static STRETCHER_INFO stretcher_info[NUM_STRETCHERS] = -{ - { 0, 0, 0, 0, 0, 0, NULL, 0 }, - { 0, 0, 0, 0, 0, 0, NULL, 0 }, - { 0, 0, 0, 0, 0, 0, NULL, 0 }, - { 0, 0, 0, 0, 0, 0, NULL, 0 }, - { 0, 0, 0, 0, 0, 0, NULL, 0 }, - { 0, 0, 0, 0, 0, 0, NULL, 0 }, - { 0, 0, 0, 0, 0, 0, NULL, 0 }, - { 0, 0, 0, 0, 0, 0, NULL, 0 } -}; - - +static STRETCHER_INFO stretcher_info[NUM_STRETCHERS]; static int stretcher_count = 0; - static int stretcher_virgin = TRUE; @@ -251,11 +240,14 @@ int i; for (i=0; i>= 2; - _do_stretch(source, dest, stretcher_info[i].data, sx>>16, sy, syd, + _do_stretch(source, dest, stretcher_info[i].exec, sx>>16, sy, syd, dest_x, dest_y, dest_height, dest->vtable->color_depth); stretcher_info[i].lru = stretcher_count; return; @@ -382,17 +383,18 @@ } } - /* make sure all allocated memory is freed atexit */ - if (stretcher_virgin) { - stretcher_virgin = FALSE; - _add_exit_func(free_stretchers, "free_stretchers"); - } - + #ifdef USE_MMAP_GEN_CODE_BUF + _exec_map = stretcher_info[best].exec; + _rw_map = stretcher_info[best].rw; + _map_size = stretcher_info[best].size; + _map_fd = stretcher_info[best].fd; + #else prev_scratch_mem = _scratch_mem; prev_scratch_mem_size = _scratch_mem_size; - _scratch_mem = stretcher_info[best].data; + _scratch_mem = stretcher_info[best].exec; _scratch_mem_size = stretcher_info[best].size; + #endif if (is_linear_bitmap(dest)) { /* build a simple linear stretcher */ @@ -439,7 +441,7 @@ #ifdef ALLEGRO_WINDOWS /* Play nice with Windows executable memory protection */ VirtualProtect(_scratch_mem, _scratch_mem_size, PAGE_EXECUTE_READWRITE, &old_protect); - #elif defined(HAVE_MPROTECT) + #elif defined(HAVE_MPROTECT) && !defined(USE_MMAP_GEN_CODE_BUF) { char *p = (char *)((unsigned long)_scratch_mem & ~(PAGE_SIZE-1ul)); if (mprotect(p, _scratch_mem_size + ((char *)_scratch_mem - p), @@ -448,22 +450,29 @@ } #endif - /* call the stretcher */ - _do_stretch(source, dest, _scratch_mem, sx>>16, sy, syd, - dest_x, dest_y, dest_height, dest->vtable->color_depth); - - /* and store it in the cache */ + /* store it in the cache */ stretcher_info[best].sx = sx; stretcher_info[best].sxd = sxd; stretcher_info[best].dest_width = dest_width; stretcher_info[best].depth = dest->vtable->color_depth; stretcher_info[best].flags = flags; stretcher_info[best].lru = stretcher_count; - stretcher_info[best].data = _scratch_mem; + #ifdef USE_MMAP_GEN_CODE_BUF + stretcher_info[best].exec = _exec_map; + stretcher_info[best].rw = _rw_map; + stretcher_info[best].size = _map_size; + stretcher_info[best].fd = _map_fd; + #else + stretcher_info[best].exec = _scratch_mem; stretcher_info[best].size = _scratch_mem_size; _scratch_mem = prev_scratch_mem; _scratch_mem_size = prev_scratch_mem_size; + #endif + + /* and call the stretcher */ + _do_stretch(source, dest, stretcher_info[best].exec, sx>>16, sy, syd, + dest_x, dest_y, dest_height, dest->vtable->color_depth); } diff -ur allegro-4.2.0.orig/src/i386/opcodes.h allegro-4.2.0/src/i386/opcodes.h --- allegro-4.2.0.orig/src/i386/opcodes.h 2000-05-14 22:17:13.000000000 +0200 +++ allegro-4.2.0/src/i386/opcodes.h 2006-03-13 23:00:31.000000000 +0100 @@ -19,6 +19,51 @@ #ifndef OPCODES_H #define OPCODES_H +/* mremap is only available under Linux, so is selinux which is the reason for + USE_MMAP_GEN_CODE_BUF so that is no problem. */ +#ifdef ALLEGRO_LINUX + #define USE_MMAP_GEN_CODE_BUF + #define __USE_GNU /* for mremap */ + #include /* for mkstemp */ + #include /* for unlink */ + #include /* for PAGE_SIZE */ + #include /* for mmap */ + + static void *_exec_map; + static void *_rw_map; + static int _map_size; + static int _map_fd; + + #define GROW_GEN_CODE_BUF(size) \ + if (!_map_size) { \ + /* Create backing file. FIXME: error-checking, but how? */ \ + char tempfile_name[] = "/tmp/allegroXXXXXX"; \ + _map_fd = mkstemp(tempfile_name); \ + unlink(tempfile_name); \ + /* Grow backing file to multiple of page size */ \ + _map_size = (size + (PAGE_SIZE-1)) & ~(PAGE_SIZE-1); \ + ftruncate(_map_fd, _map_size); \ + /* And create the 2 mappings */ \ + _exec_map = mmap(0, _map_size, PROT_EXEC | PROT_READ, MAP_SHARED, \ + _map_fd, 0); \ + _rw_map = mmap(0, _map_size, PROT_READ | PROT_WRITE, MAP_SHARED, \ + _map_fd, 0); \ + } \ + else if (size > _map_size) { \ + int old_size = _map_size; \ + /* Grow backing file to multiple of page size */ \ + _map_size = (size + (PAGE_SIZE-1)) & ~(PAGE_SIZE-1); \ + ftruncate(_map_fd, _map_size); \ + /* And remap the 2 mappings */ \ + _exec_map = mremap(_exec_map, old_size, _map_size, MREMAP_MAYMOVE); \ + _rw_map = mremap(_rw_map, old_size, _map_size, MREMAP_MAYMOVE); \ + } + + #define GEN_CODE_BUF _rw_map +#else + #define GROW_GEN_CODE_BUF(size) _grow_scratch_mem(size) + #define GEN_CODE_BUF _scratch_mem +#endif #ifdef ALLEGRO_ASM_USE_FS #define FS_PREFIX() COMPILER_BYTE(0x64) @@ -30,37 +75,37 @@ #define COMPILER_BYTE(val) { \ - *(((unsigned char *)_scratch_mem)+compiler_pos) = val; \ + *(((unsigned char *)GEN_CODE_BUF)+compiler_pos) = val; \ compiler_pos++; \ } #define COMPILER_WORD(val) { \ - *((unsigned short *)(((char *)_scratch_mem)+compiler_pos)) = val; \ + *((unsigned short *)(((char *)GEN_CODE_BUF)+compiler_pos)) = val; \ compiler_pos += 2; \ } #define COMPILER_LONG(val) { \ - *((unsigned long *)(((char *)_scratch_mem)+compiler_pos)) = val; \ + *((unsigned long *)(((char *)GEN_CODE_BUF)+compiler_pos)) = val; \ compiler_pos += 4; \ } #define COMPILER_INC_ESI() { \ - _grow_scratch_mem(compiler_pos+1); \ + GROW_GEN_CODE_BUF(compiler_pos+1); \ COMPILER_BYTE(0x46); /* incl %esi */ \ } #define COMPILER_INC_EDI() { \ - _grow_scratch_mem(compiler_pos+1); \ + GROW_GEN_CODE_BUF(compiler_pos+1); \ COMPILER_BYTE(0x47); /* incl %edi */ \ } #define COMPILER_ADD_ESI(val) { \ - _grow_scratch_mem(compiler_pos+6); \ + GROW_GEN_CODE_BUF(compiler_pos+6); \ COMPILER_BYTE(0x81); /* addl $val, %esi */ \ COMPILER_BYTE(0xC6); \ COMPILER_LONG(val); \ @@ -68,87 +113,87 @@ #define COMPILER_ADD_ECX_EAX() { \ - _grow_scratch_mem(compiler_pos+2); \ + GROW_GEN_CODE_BUF(compiler_pos+2); \ COMPILER_BYTE(0x01); /* addl %ecx, %eax */ \ COMPILER_BYTE(0xC8); \ } #define COMPILER_MOV_EAX(val) { \ - _grow_scratch_mem(compiler_pos+5); \ + GROW_GEN_CODE_BUF(compiler_pos+5); \ COMPILER_BYTE(0xB8); /* movl $val, %eax */ \ COMPILER_LONG(val); \ } #define COMPILER_MOV_ECX(val) { \ - _grow_scratch_mem(compiler_pos+5); \ + GROW_GEN_CODE_BUF(compiler_pos+5); \ COMPILER_BYTE(0xB9); /* movl $val, %ecx */ \ COMPILER_LONG(val); \ } #define COMPILER_MOV_EDX(val) { \ - _grow_scratch_mem(compiler_pos+5); \ + GROW_GEN_CODE_BUF(compiler_pos+5); \ COMPILER_BYTE(0xBA); /* movl $val, %edx */ \ COMPILER_LONG(val); \ } #define COMPILER_MOV_EDI_EAX() { \ - _grow_scratch_mem(compiler_pos+2); \ + GROW_GEN_CODE_BUF(compiler_pos+2); \ COMPILER_BYTE(0x89); /* movl %edi, %eax */ \ COMPILER_BYTE(0xF8); \ } #define COMPILER_CALL_ESI() { \ - _grow_scratch_mem(compiler_pos+2); \ + GROW_GEN_CODE_BUF(compiler_pos+2); \ COMPILER_BYTE(0xFF); /* call *%esi */ \ COMPILER_BYTE(0xD6); \ } #define COMPILER_OUTW() { \ - _grow_scratch_mem(compiler_pos+2); \ + GROW_GEN_CODE_BUF(compiler_pos+2); \ COMPILER_BYTE(0x66); /* outw %ax, %dx */ \ COMPILER_BYTE(0xEF); \ } #define COMPILER_PUSH_ESI() { \ - _grow_scratch_mem(compiler_pos+1); \ + GROW_GEN_CODE_BUF(compiler_pos+1); \ COMPILER_BYTE(0x56); /* pushl %esi */ \ } #define COMPILER_PUSH_EDI() { \ - _grow_scratch_mem(compiler_pos+1); \ + GROW_GEN_CODE_BUF(compiler_pos+1); \ COMPILER_BYTE(0x57); /* pushl %edi */ \ } #define COMPILER_POP_ESI() { \ - _grow_scratch_mem(compiler_pos+1); \ + GROW_GEN_CODE_BUF(compiler_pos+1); \ COMPILER_BYTE(0x5E); /* popl %esi */ \ } #define COMPILER_POP_EDI() { \ - _grow_scratch_mem(compiler_pos+1); \ + GROW_GEN_CODE_BUF(compiler_pos+1); \ COMPILER_BYTE(0x5F); /* popl %edi */ \ } #define COMPILER_REP_MOVSB() { \ - _grow_scratch_mem(compiler_pos+2); \ + GROW_GEN_CODE_BUF(compiler_pos+2); \ COMPILER_BYTE(0xF2); /* rep */ \ COMPILER_BYTE(0xA4); /* movsb */ \ } #define COMPILER_REP_MOVSW() { \ - _grow_scratch_mem(compiler_pos+3); \ + GROW_GEN_CODE_BUF(compiler_pos+3); \ COMPILER_BYTE(0xF3); /* rep */ \ COMPILER_BYTE(0x66); /* word prefix */ \ COMPILER_BYTE(0xA5); /* movsw */ \ @@ -156,14 +201,14 @@ #define COMPILER_REP_MOVSL() { \ - _grow_scratch_mem(compiler_pos+2); \ + GROW_GEN_CODE_BUF(compiler_pos+2); \ COMPILER_BYTE(0xF3); /* rep */ \ COMPILER_BYTE(0xA5); /* movsl */ \ } #define COMPILER_REP_MOVSL2() { \ - _grow_scratch_mem(compiler_pos+17); \ + GROW_GEN_CODE_BUF(compiler_pos+17); \ COMPILER_BYTE(0x8D); /* leal (%ecx, %ecx, 2), %ecx */ \ COMPILER_BYTE(0x0C); \ COMPILER_BYTE(0x49); \ @@ -185,7 +230,7 @@ #define COMPILER_LODSB() { \ - _grow_scratch_mem(compiler_pos+3); \ + GROW_GEN_CODE_BUF(compiler_pos+3); \ COMPILER_BYTE(0x8A); /* movb (%esi), %al */ \ COMPILER_BYTE(0x06); \ COMPILER_BYTE(0x46); /* incl %esi */ \ @@ -193,7 +238,7 @@ #define COMPILER_LODSW() { \ - _grow_scratch_mem(compiler_pos+6); \ + GROW_GEN_CODE_BUF(compiler_pos+6); \ COMPILER_BYTE(0x66); /* word prefix */ \ COMPILER_BYTE(0x8B); /* movw (%esi), %ax */ \ COMPILER_BYTE(0x06); \ @@ -204,7 +249,7 @@ #define COMPILER_LODSL() { \ - _grow_scratch_mem(compiler_pos+5); \ + GROW_GEN_CODE_BUF(compiler_pos+5); \ COMPILER_BYTE(0x8B); /* movl (%esi), %eax */ \ COMPILER_BYTE(0x06); \ COMPILER_BYTE(0x83); /* addl $4, %esi */ \ @@ -214,7 +259,7 @@ #define COMPILER_LODSL2() { \ - _grow_scratch_mem(compiler_pos+15); \ + GROW_GEN_CODE_BUF(compiler_pos+15); \ COMPILER_BYTE(0x8B); /* movl (%esi), %eax */ \ COMPILER_BYTE(0x06); \ COMPILER_BYTE(0x25); /* andl $0xFFFFFF, %eax */ \ @@ -231,7 +276,7 @@ #define COMPILER_STOSB() { \ - _grow_scratch_mem(compiler_pos+4); \ + GROW_GEN_CODE_BUF(compiler_pos+4); \ COMPILER_BYTE(0x26); /* movb %al, %es:(%edi) */ \ COMPILER_BYTE(0x88); \ COMPILER_BYTE(0x07); \ @@ -240,7 +285,7 @@ #define COMPILER_STOSW() { \ - _grow_scratch_mem(compiler_pos+7); \ + GROW_GEN_CODE_BUF(compiler_pos+7); \ COMPILER_BYTE(0x26); /* es segment prefix */ \ COMPILER_BYTE(0x66); /* word prefix */ \ COMPILER_BYTE(0x89); /* movw %ax, %es:(%edi) */ \ @@ -252,7 +297,7 @@ #define COMPILER_STOSL() { \ - _grow_scratch_mem(compiler_pos+6); \ + GROW_GEN_CODE_BUF(compiler_pos+6); \ COMPILER_BYTE(0x26); /* es segment prefix */ \ COMPILER_BYTE(0x89); /* movl %eax, %es:(%edi) */ \ COMPILER_BYTE(0x07); \ @@ -263,7 +308,7 @@ #define COMPILER_STOSL2() { \ - _grow_scratch_mem(compiler_pos+11); \ + GROW_GEN_CODE_BUF(compiler_pos+11); \ COMPILER_BYTE(0x66); /* word prefix */ \ COMPILER_BYTE(0x26); /* es segment prefix */ \ COMPILER_BYTE(0x89); /* movw %ax, %es:(%edi) */ \ @@ -279,7 +324,7 @@ #define COMPILER_MASKED_STOSB(mask_color) { \ - _grow_scratch_mem(compiler_pos+8); \ + GROW_GEN_CODE_BUF(compiler_pos+8); \ COMPILER_BYTE(0x08); /* orb %al, %al */ \ COMPILER_BYTE(0xC0); \ COMPILER_BYTE(0x74); /* jz skip */ \ @@ -292,7 +337,7 @@ #define COMPILER_MASKED_STOSW(mask_color) { \ - _grow_scratch_mem(compiler_pos+13); \ + GROW_GEN_CODE_BUF(compiler_pos+13); \ COMPILER_BYTE(0x66); /* word prefix */ \ COMPILER_BYTE(0x3D); /* cmpw mask_color, %ax */ \ COMPILER_WORD(mask_color); \ @@ -309,7 +354,7 @@ #define COMPILER_MASKED_STOSL(mask_color) { \ - _grow_scratch_mem(compiler_pos+13); \ + GROW_GEN_CODE_BUF(compiler_pos+13); \ COMPILER_BYTE(0x3D); /* cmpl mask_color, %eax */ \ COMPILER_LONG(mask_color); \ COMPILER_BYTE(0x74); /* jz skip */ \ @@ -324,7 +369,7 @@ #define COMPILER_MASKED_STOSL2(mask_color) { \ - _grow_scratch_mem(compiler_pos+18); \ + GROW_GEN_CODE_BUF(compiler_pos+18); \ COMPILER_BYTE(0x3D); /* cmpl mask_color, %eax */ \ COMPILER_LONG(mask_color); \ COMPILER_BYTE(0x74); /* jz skip */ \ @@ -360,7 +405,7 @@ #define COMPILER_MOVB_IMMED(offset, val) { \ - _grow_scratch_mem(MOV_IMMED_SIZE(2+FS_SIZE, offset)); \ + GROW_GEN_CODE_BUF(MOV_IMMED_SIZE(2+FS_SIZE, offset)); \ FS_PREFIX(); /* fs: */ \ COMPILER_BYTE(0xC6); /* movb $val, offset(%eax) */ \ MOV_IMMED(offset); \ @@ -369,7 +414,7 @@ #define COMPILER_MOVW_IMMED(offset, val) { \ - _grow_scratch_mem(MOV_IMMED_SIZE(4+FS_SIZE, offset)); \ + GROW_GEN_CODE_BUF(MOV_IMMED_SIZE(4+FS_SIZE, offset)); \ COMPILER_BYTE(0x66); /* word prefix */ \ FS_PREFIX(); /* fs: */ \ COMPILER_BYTE(0xC7); /* movw $val, offset(%eax) */ \ @@ -379,7 +424,7 @@ #define COMPILER_MOVL_IMMED(offset, val) { \ - _grow_scratch_mem(MOV_IMMED_SIZE(5+FS_SIZE, offset)); \ + GROW_GEN_CODE_BUF(MOV_IMMED_SIZE(5+FS_SIZE, offset)); \ FS_PREFIX(); /* fs: */ \ COMPILER_BYTE(0xC7); /* movl $val, offset(%eax) */ \ MOV_IMMED(offset); \ @@ -388,7 +433,7 @@ #define COMPILER_RET() { \ - _grow_scratch_mem(compiler_pos+1); \ + GROW_GEN_CODE_BUF(compiler_pos+1); \ COMPILER_BYTE(0xC3); /* ret */ \ }