diff options
Diffstat (limited to 'mesalib')
-rw-r--r-- | mesalib/src/mapi/mapi/entry.c | 65 | ||||
-rw-r--r-- | mesalib/src/mapi/mapi/entry.h | 49 | ||||
-rw-r--r-- | mesalib/src/mapi/mapi/entry_x86-64_tls.h | 97 | ||||
-rw-r--r-- | mesalib/src/mapi/mapi/entry_x86_tls.h | 120 | ||||
-rw-r--r-- | mesalib/src/mapi/mapi/entry_x86_tsd.h | 89 | ||||
-rw-r--r-- | mesalib/src/mapi/mapi/mapi.c | 191 | ||||
-rw-r--r-- | mesalib/src/mapi/mapi/mapi.h | 66 | ||||
-rw-r--r-- | mesalib/src/mapi/mapi/mapi_abi.py | 402 | ||||
-rw-r--r-- | mesalib/src/mapi/mapi/mapi_tmp.h | 211 | ||||
-rw-r--r-- | mesalib/src/mapi/mapi/sources.mak | 19 | ||||
-rw-r--r-- | mesalib/src/mapi/mapi/stub.c | 180 | ||||
-rw-r--r-- | mesalib/src/mapi/mapi/stub.h | 52 | ||||
-rw-r--r-- | mesalib/src/mapi/mapi/table.c | 56 | ||||
-rw-r--r-- | mesalib/src/mapi/mapi/table.h | 76 | ||||
-rw-r--r-- | mesalib/src/mapi/mapi/u_compiler.h | 48 | ||||
-rw-r--r-- | mesalib/src/mapi/mapi/u_current.c | 277 | ||||
-rw-r--r-- | mesalib/src/mapi/mapi/u_current.h | 102 | ||||
-rw-r--r-- | mesalib/src/mapi/mapi/u_execmem.c | 145 | ||||
-rw-r--r-- | mesalib/src/mapi/mapi/u_execmem.h | 7 | ||||
-rw-r--r-- | mesalib/src/mapi/mapi/u_macros.h | 12 | ||||
-rw-r--r-- | mesalib/src/mapi/mapi/u_thread.c | 254 | ||||
-rw-r--r-- | mesalib/src/mapi/mapi/u_thread.h | 201 |
22 files changed, 2719 insertions, 0 deletions
diff --git a/mesalib/src/mapi/mapi/entry.c b/mesalib/src/mapi/mapi/entry.c new file mode 100644 index 000000000..fdf2a89c5 --- /dev/null +++ b/mesalib/src/mapi/mapi/entry.c @@ -0,0 +1,65 @@ +/* + * Mesa 3-D graphics library + * Version: 7.9 + * + * Copyright (C) 2010 LunarG Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Chia-I Wu <olv@lunarg.com> + */ + +#include "entry.h" + +#if defined(USE_X86_ASM) && defined(__GNUC__) +# ifdef GLX_USE_TLS +# include "entry_x86_tls.h" +# else +# include "entry_x86_tsd.h" +# endif +#elif defined(USE_X86_64_ASM) && defined(__GNUC__) && defined(GLX_USE_TLS) +# include "entry_x86-64_tls.h" +#else + +#include <stdlib.h> +#include "u_current.h" +#include "table.h" + +/* C version of the public entries */ +#define MAPI_TMP_PUBLIC_ENTRIES +#include "mapi_tmp.h" + +void +entry_patch_public(void) +{ +} + +mapi_func +entry_generate(int slot) +{ + return NULL; +} + +void +entry_patch(mapi_func entry, int slot) +{ +} + +#endif /* asm */ diff --git a/mesalib/src/mapi/mapi/entry.h b/mesalib/src/mapi/mapi/entry.h new file mode 100644 index 000000000..48ed3f9ec --- /dev/null +++ b/mesalib/src/mapi/mapi/entry.h @@ -0,0 +1,49 @@ +/* + * Mesa 3-D graphics library + * Version: 7.9 + * + * Copyright (C) 2010 LunarG Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Chia-I Wu <olv@lunarg.com> + */ + +#ifndef _ENTRY_H_ +#define _ENTRY_H_ + +#include "u_compiler.h" +#include "stub.h" + +/* declare public entries */ +#define MAPI_TMP_DEFINES +#define MAPI_TMP_PUBLIC_DECLARES +#include "mapi_tmp.h" + +void +entry_patch_public(void); + +mapi_func +entry_generate(int slot); + +void +entry_patch(mapi_func entry, int slot); + +#endif /* _ENTRY_H_ */ diff --git a/mesalib/src/mapi/mapi/entry_x86-64_tls.h b/mesalib/src/mapi/mapi/entry_x86-64_tls.h new file mode 100644 index 000000000..2fbe73b5b --- /dev/null +++ b/mesalib/src/mapi/mapi/entry_x86-64_tls.h @@ -0,0 +1,97 @@ +/* + * Mesa 3-D graphics library + * Version: 7.9 + * + * Copyright (C) 2010 LunarG Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Chia-I Wu <olv@lunarg.com> + */ + +#include <string.h> +#include "u_execmem.h" +#include "u_macros.h" + +__asm__(".text"); + +__asm__("x86_64_current_tls:\n\t" + "movq u_current_table_tls@GOTTPOFF(%rip), %rax\n\t" + "ret"); + +#define STUB_ASM_ENTRY(func) \ + ".globl " func "\n" \ + ".type " func ", @function\n" \ + ".balign 32\n" \ + func ":" + +#define STUB_ASM_CODE(slot) \ + "movq u_current_table_tls@GOTTPOFF(%rip), %rax\n\t" \ + "movq %fs:(%rax), %r11\n\t" \ + "jmp *(8 * " slot ")(%r11)" + +#define MAPI_TMP_STUB_ASM_GCC +#include "mapi_tmp.h" + +extern unsigned long +x86_64_current_tls(); + +void +entry_patch_public(void) +{ +} + +void +entry_patch(mapi_func entry, int slot) +{ + char *code = (char *) entry; + *((unsigned int *) (code + 12)) = slot * sizeof(mapi_func); +} + +mapi_func +entry_generate(int slot) +{ + const char code_templ[16] = { + /* movq %fs:0, %r11 */ + 0x64, 0x4c, 0x8b, 0x1c, 0x25, 0x00, 0x00, 0x00, 0x00, + /* jmp *0x1234(%r11) */ + 0x41, 0xff, 0xa3, 0x34, 0x12, 0x00, 0x00, + }; + unsigned long addr; + void *code; + mapi_func entry; + + addr = x86_64_current_tls(); + if ((addr >> 32) != 0xffffffff) + return NULL; + addr &= 0xffffffff; + + code = u_execmem_alloc(sizeof(code_templ)); + if (!code) + return NULL; + + memcpy(code, code_templ, sizeof(code_templ)); + + *((unsigned int *) (code + 5)) = addr; + entry = (mapi_func) code; + entry_patch(entry, slot); + + return entry; +} diff --git a/mesalib/src/mapi/mapi/entry_x86_tls.h b/mesalib/src/mapi/mapi/entry_x86_tls.h new file mode 100644 index 000000000..d4f7d98cf --- /dev/null +++ b/mesalib/src/mapi/mapi/entry_x86_tls.h @@ -0,0 +1,120 @@ +/* + * Mesa 3-D graphics library + * Version: 7.9 + * + * Copyright (C) 2010 LunarG Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Chia-I Wu <olv@lunarg.com> + */ + +#include <string.h> +#include "u_execmem.h" +#include "u_macros.h" + +__asm__(".text"); + +__asm__("x86_current_tls:\n\t" + "call 1f\n" + "1:\n\t" + "popl %eax\n\t" + "addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %eax\n\t" + "movl u_current_table_tls@GOTNTPOFF(%eax), %eax\n\t" + "ret"); + +#ifndef GLX_X86_READONLY_TEXT +__asm__(".section wtext, \"awx\", @progbits\n" + ".balign 16\n" + "x86_entry_start:"); +#endif /* GLX_X86_READONLY_TEXT */ + +#define STUB_ASM_ENTRY(func) \ + ".globl " func "\n" \ + ".type " func ", @function\n" \ + ".balign 16\n" \ + func ":" + +#define STUB_ASM_CODE(slot) \ + "call x86_current_tls\n\t" \ + "movl %gs:(%eax), %eax\n\t" \ + "jmp *(4 * " slot ")(%eax)" + +#define MAPI_TMP_STUB_ASM_GCC +#include "mapi_tmp.h" + +#ifndef GLX_X86_READONLY_TEXT +__asm__(".balign 16\n" + "x86_entry_end:"); +__asm__(".text"); +#endif /* GLX_X86_READONLY_TEXT */ + +extern unsigned long +x86_current_tls(); + +void +entry_patch_public(void) +{ +#ifndef GLX_X86_READONLY_TEXT + extern char x86_entry_start[]; + extern char x86_entry_end[]; + char patch[8] = { + 0x65, 0xa1, 0x00, 0x00, 0x00, 0x00, /* movl %gs:0x0, %eax */ + 0x90, 0x90 /* nop's */ + }; + char *entry; + + *((unsigned long *) (patch + 2)) = x86_current_tls(); + + for (entry = x86_entry_start; entry < x86_entry_end; entry += 16) + memcpy(entry, patch, sizeof(patch)); +#endif +} + +void +entry_patch(mapi_func entry, int slot) +{ + char *code = (char *) entry; + *((unsigned long *) (code + 8)) = slot * sizeof(mapi_func); +} + +mapi_func +entry_generate(int slot) +{ + const char code_templ[16] = { + 0x65, 0xa1, 0x00, 0x00, 0x00, 0x00, /* movl %gs:0x0, %eax */ + 0xff, 0xa0, 0x34, 0x12, 0x00, 0x00, /* jmp *0x1234(%eax) */ + 0x90, 0x90, 0x90, 0x90 /* nop's */ + }; + void *code; + mapi_func entry; + + code = u_execmem_alloc(sizeof(code_templ)); + if (!code) + return NULL; + + memcpy(code, code_templ, sizeof(code_templ)); + + *((unsigned long *) (code + 2)) = x86_current_tls(); + entry = (mapi_func) code; + entry_patch(entry, slot); + + return entry; +} diff --git a/mesalib/src/mapi/mapi/entry_x86_tsd.h b/mesalib/src/mapi/mapi/entry_x86_tsd.h new file mode 100644 index 000000000..f37c7473a --- /dev/null +++ b/mesalib/src/mapi/mapi/entry_x86_tsd.h @@ -0,0 +1,89 @@ +/* + * Mesa 3-D graphics library + * Version: 7.9 + * + * Copyright (C) 2010 LunarG Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Chia-I Wu <olv@lunarg.com> + */ + +#include <string.h> +#include "u_execmem.h" +#include "u_macros.h" + +#define X86_ENTRY_SIZE 32 + +__asm__(".text"); + +#define STUB_ASM_ENTRY(func) \ + ".globl " func "\n" \ + ".type " func ", @function\n" \ + ".balign 32\n" \ + func ":" + +#define STUB_ASM_CODE(slot) \ + "movl u_current_table, %eax\n\t" \ + "testl %eax, %eax\n\t" \ + "je 1f\n\t" \ + "jmp *(4 * " slot ")(%eax)\n" \ + "1:\n\t" \ + "call u_current_get_internal\n\t"\ + "jmp *(4 * " slot ")(%eax)" + +#define MAPI_TMP_STUB_ASM_GCC +#include "mapi_tmp.h" + +__asm__(".balign 32\n" + "x86_entry_end:"); + +void +entry_patch_public(void) +{ +} + +void +entry_patch(mapi_func entry, int slot) +{ + char *code = (char *) entry; + + *((unsigned long *) (code + 11)) = slot * sizeof(mapi_func); + *((unsigned long *) (code + 22)) = slot * sizeof(mapi_func); +} + +mapi_func +entry_generate(int slot) +{ + extern const char x86_entry_end[]; + const char *code_templ = x86_entry_end - X86_ENTRY_SIZE; + void *code; + mapi_func entry; + + code = u_execmem_alloc(X86_ENTRY_SIZE); + if (!code) + return NULL; + + memcpy(code, code_templ, X86_ENTRY_SIZE); + entry = (mapi_func) code; + entry_patch(entry, slot); + + return entry; +} diff --git a/mesalib/src/mapi/mapi/mapi.c b/mesalib/src/mapi/mapi/mapi.c new file mode 100644 index 000000000..2f1c3fff6 --- /dev/null +++ b/mesalib/src/mapi/mapi/mapi.c @@ -0,0 +1,191 @@ +/* + * Mesa 3-D graphics library + * Version: 7.9 + * + * Copyright (C) 2010 LunarG Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Chia-I Wu <olv@lunarg.com> + */ + +#include <stdlib.h> +#include <string.h> + +#include "u_current.h" +#include "u_thread.h" +#include "mapi.h" +#include "stub.h" +#include "table.h" + +/* dynamic stubs will run out before this array */ +#define MAPI_MAX_STUBS (sizeof(struct mapi_table) / sizeof(mapi_func)) +static const struct mapi_stub *mapi_stub_map[MAPI_MAX_STUBS]; +static int mapi_num_stubs; + +static const struct mapi_stub * +get_stub(const char *name, const struct mapi_stub *alias) +{ + const struct mapi_stub *stub; + + stub = stub_find_public(name); + if (!stub) { + struct mapi_stub *dyn = stub_find_dynamic(name, 1); + if (dyn) { + stub_fix_dynamic(dyn, alias); + stub = dyn; + } + } + + return stub; +} + +/** + * Initialize mapi. spec consists of NULL-separated strings. The first string + * denotes the version. It is followed by variable numbers of entries. Each + * entry can have multiple names. An empty name terminates an entry. An empty + * entry terminates the spec. A spec of two entries, Foo and Bar, is as + * follows + * + * "1\0" + * "Foo\0" + * "FooEXT\0" + * "\0" + * "Bar\0" + * "\0" + */ +void +mapi_init(const char *spec) +{ + u_mutex_declare_static(mutex); + const char *p; + int ver, count; + + u_mutex_lock(mutex); + + /* already initialized */ + if (mapi_num_stubs) { + u_mutex_unlock(mutex); + return; + } + + count = 0; + p = spec; + + /* parse version string */ + ver = atoi(p); + if (ver != 1) { + u_mutex_unlock(mutex); + return; + } + p += strlen(p) + 1; + + while (*p) { + const struct mapi_stub *stub; + + stub = get_stub(p, NULL); + /* out of dynamic entries */ + if (!stub) + break; + p += strlen(p) + 1; + + while (*p) { + get_stub(p, stub); + p += strlen(p) + 1; + } + + mapi_stub_map[count++] = stub; + p++; + } + + mapi_num_stubs = count; + + u_mutex_unlock(mutex); +} + +/** + * Return the address of an entry. Optionally generate the entry if it does + * not exist. + */ +mapi_proc +mapi_get_proc_address(const char *name) +{ + const struct mapi_stub *stub; + + stub = stub_find_public(name); + if (!stub) + stub = stub_find_dynamic(name, 0); + + return (stub) ? (mapi_proc) stub->addr : NULL; +} + +/** + * Create a dispatch table. + */ +struct mapi_table * +mapi_table_create(void) +{ + const struct mapi_table *noop = table_get_noop(); + struct mapi_table *tbl; + + tbl = malloc(sizeof(*tbl)); + if (tbl) + memcpy(tbl, noop, sizeof(*tbl)); + + return tbl; +} + +/** + * Destroy a dispatch table. + */ +void +mapi_table_destroy(struct mapi_table *tbl) +{ + free(tbl); +} + +/** + * Fill a dispatch table. The order of the procs is determined when mapi_init + * is called. + */ +void +mapi_table_fill(struct mapi_table *tbl, const mapi_proc *procs) +{ + const struct mapi_table *noop = table_get_noop(); + int i; + + for (i = 0; i < mapi_num_stubs; i++) { + const struct mapi_stub *stub = mapi_stub_map[i]; + mapi_func func = (mapi_func) procs[i]; + + if (!func) + func = table_get_func(noop, stub); + table_set_func(tbl, stub, func); + } +} + +/** + * Make a dispatch table current. + */ +void +mapi_table_make_current(const struct mapi_table *tbl) +{ + u_current_set(tbl); +} diff --git a/mesalib/src/mapi/mapi/mapi.h b/mesalib/src/mapi/mapi/mapi.h new file mode 100644 index 000000000..c7e43e22e --- /dev/null +++ b/mesalib/src/mapi/mapi/mapi.h @@ -0,0 +1,66 @@ +/* + * Mesa 3-D graphics library + * Version: 7.9 + * + * Copyright (C) 2010 LunarG Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Chia-I Wu <olv@lunarg.com> + */ + +#ifndef _MAPI_H_ +#define _MAPI_H_ + +#include "u_compiler.h" + +#ifdef _WIN32 +#ifdef MAPI_DLL_EXPORTS +#define MAPI_EXPORT __declspec(dllexport) +#else +#define MAPI_EXPORT __declspec(dllimport) +#endif +#else /* _WIN32 */ +#define MAPI_EXPORT PUBLIC +#endif + +typedef void (*mapi_proc)(void); + +struct mapi_table; + +MAPI_EXPORT void +mapi_init(const char *spec); + +MAPI_EXPORT mapi_proc +mapi_get_proc_address(const char *name); + +MAPI_EXPORT struct mapi_table * +mapi_table_create(void); + +MAPI_EXPORT void +mapi_table_destroy(struct mapi_table *tbl); + +MAPI_EXPORT void +mapi_table_fill(struct mapi_table *tbl, const mapi_proc *procs); + +MAPI_EXPORT void +mapi_table_make_current(const struct mapi_table *tbl); + +#endif /* _MAPI_H_ */ diff --git a/mesalib/src/mapi/mapi/mapi_abi.py b/mesalib/src/mapi/mapi/mapi_abi.py new file mode 100644 index 000000000..440eb4bb9 --- /dev/null +++ b/mesalib/src/mapi/mapi/mapi_abi.py @@ -0,0 +1,402 @@ +#!/usr/bin/env python + +# Mesa 3-D graphics library +# Version: 7.9 +# +# Copyright (C) 2010 LunarG Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# DEALINGS IN THE SOFTWARE. +# +# Authors: +# Chia-I Wu <olv@lunarg.com> + +import sys +import re +from optparse import OptionParser + +# number of dynamic entries +ABI_NUM_DYNAMIC_ENTRIES = 256 + +class ABIEntry(object): + """Represent an ABI entry.""" + + _match_c_param = re.compile( + '^(?P<type>[\w\s*]+?)(?P<name>\w+)(\[(?P<array>\d+)\])?$') + + def __init__(self, cols, attrs): + self._parse(cols) + + self.slot = attrs['slot'] + self.hidden = attrs['hidden'] + self.alias = attrs['alias'] + + def c_prototype(self): + return '%s %s(%s)' % (self.c_return(), self.name, self.c_params()) + + def c_return(self): + ret = self.ret + if not ret: + ret = 'void' + + return ret + + def c_params(self): + """Return the parameter list used in the entry prototype.""" + c_params = [] + for t, n, a in self.params: + sep = '' if t.endswith('*') else ' ' + arr = '[%d]' % a if a else '' + c_params.append(t + sep + n + arr) + if not c_params: + c_params.append('void') + + return ", ".join(c_params) + + def c_args(self): + """Return the argument list used in the entry invocation.""" + c_args = [] + for t, n, a in self.params: + c_args.append(n) + + return ", ".join(c_args) + + def _parse(self, cols): + ret = cols.pop(0) + if ret == 'void': + ret = None + + name = cols.pop(0) + + params = [] + if not cols: + raise Exception(cols) + elif len(cols) == 1 and cols[0] == 'void': + pass + else: + for val in cols: + params.append(self._parse_param(val)) + + self.ret = ret + self.name = name + self.params = params + + def _parse_param(self, c_param): + m = self._match_c_param.match(c_param) + if not m: + raise Exception('unrecognized param ' + c_param) + + c_type = m.group('type').strip() + c_name = m.group('name') + c_array = m.group('array') + c_array = int(c_array) if c_array else 0 + + return (c_type, c_name, c_array) + + def __str__(self): + return self.c_prototype() + + def __cmp__(self, other): + # compare slot, alias, and then name + res = cmp(self.slot, other.slot) + if not res: + if not self.alias: + res = -1 + elif not other.alias: + res = 1 + + if not res: + res = cmp(self.name, other.name) + + return res + +def abi_parse_line(line): + cols = [col.strip() for col in line.split(',')] + + attrs = { + 'slot': -1, + 'hidden': False, + 'alias': None, + } + + # extract attributes from the first column + vals = cols[0].split(':') + while len(vals) > 1: + val = vals.pop(0) + if val.startswith('slot='): + attrs['slot'] = int(val[5:]) + elif val == 'hidden': + attrs['hidden'] = True + elif val.startswith('alias='): + attrs['alias'] = val[6:] + elif not val: + pass + else: + raise Exception('unknown attribute %s' % val) + cols[0] = vals[0] + + return (attrs, cols) + +def abi_parse(filename): + """Parse a CSV file for ABI entries.""" + fp = open(filename) if filename != '-' else sys.stdin + lines = [line.strip() for line in fp.readlines() + if not line.startswith('#') and line.strip()] + + entry_dict = {} + next_slot = 0 + for line in lines: + attrs, cols = abi_parse_line(line) + + # post-process attributes + if attrs['alias']: + try: + ent = entry_dict[attrs['alias']] + slot = ent.slot + except KeyError: + raise Exception('failed to alias %s' % attrs['alias']) + else: + slot = next_slot + next_slot += 1 + + if attrs['slot'] < 0: + attrs['slot'] = slot + elif attrs['slot'] != slot: + raise Exception('invalid slot in %s' % (line)) + + ent = ABIEntry(cols, attrs) + if entry_dict.has_key(ent.name): + raise Exception('%s is duplicated' % (ent.name)) + entry_dict[ent.name] = ent + + entries = entry_dict.values() + entries.sort() + + # sanity check + i = 0 + for slot in xrange(next_slot): + if entries[i].slot != slot: + raise Exception('entries are not ordered by slots') + if entries[i].alias: + raise Exception('first entry of slot %d aliases %s' + % (slot, entries[i].alias)) + while i < len(entries) and entries[i].slot == slot: + i += 1 + if i < len(entries): + raise Exception('there are %d invalid entries' % (len(entries) - 1)) + + return entries + +def abi_dynamics(): + """Return the dynamic entries.""" + entries = [] + for i in xrange(ABI_NUM_DYNAMIC_ENTRIES): + cols = ['void', 'dynamic%d' % (i), 'void'] + attrs = { 'slot': -1, 'hidden': False, 'alias': None } + entries.append(ABIEntry(cols, attrs)) + return entries + +class ABIPrinter(object): + """ABIEntry Printer""" + + def __init__(self, entries, options): + self.entries = entries + self.options = options + self._undefs = [] + + def _add_undefs(self, undefs): + self._undefs.extend(undefs) + + def output_header(self): + print '/* This file is automatically generated. Do not modify. */' + print + + def output_footer(self): + print '/* clean up */' + for m in self._undefs: + print '#undef %s' % (m) + + def output_entry(self, ent): + if ent.slot < 0: + out_ent = 'MAPI_DYNAMIC_ENTRY(%s, %s, (%s))' % \ + (ent.c_return(), ent.name, ent.c_params()) + out_code = '' + else: + if ent.alias: + macro_ent = 'MAPI_ALIAS_ENTRY' + macro_code = 'MAPI_ALIAS_CODE' + else: + macro_ent = 'MAPI_ABI_ENTRY' + macro_code = 'MAPI_ABI_CODE' + + if ent.ret: + macro_code += '_RETURN' + if ent.hidden: + macro_ent += '_HIDDEN' + macro_code += '_HIDDEN' + + if ent.alias: + out_ent = '%s(%s, %s, %s, (%s))' % (macro_ent, + ent.alias, ent.c_return(), ent.name, ent.c_params()) + out_code = '%s(%s, %s, %s, (%s))' % (macro_code, + ent.alias, ent.c_return(), ent.name, ent.c_args()) + else: + out_ent = '%s(%s, %s, (%s))' % (macro_ent, + ent.c_return(), ent.name, ent.c_params()) + out_code = '%s(%s, %s, (%s))' % (macro_code, + ent.c_return(), ent.name, ent.c_args()) + + print out_ent + if out_code: + print ' ' + out_code + + def output_entries(self, pool_offsets): + defs = [ + # normal entries + ('MAPI_ABI_ENTRY', '(ret, name, params)', ''), + ('MAPI_ABI_CODE', '(ret, name, args)', ''), + ('MAPI_ABI_CODE_RETURN', '', 'MAPI_ABI_CODE'), + # alias entries + ('MAPI_ALIAS_ENTRY', '(alias, ret, name, params)', ''), + ('MAPI_ALIAS_CODE', '(alias, ret, name, args)', ''), + ('MAPI_ALIAS_CODE_RETURN', '', 'MAPI_ALIAS_CODE'), + # hidden normal entries + ('MAPI_ABI_ENTRY_HIDDEN', '', 'MAPI_ABI_ENTRY'), + ('MAPI_ABI_CODE_HIDDEN', '', 'MAPI_ABI_CODE'), + ('MAPI_ABI_CODE_RETURN_HIDDEN', '', 'MAPI_ABI_CODE_RETURN'), + # hidden alias entries + ('MAPI_ALIAS_ENTRY_HIDDEN', '', 'MAPI_ALIAS_ENTRY'), + ('MAPI_ALIAS_CODE_HIDDEN', '', 'MAPI_ALIAS_CODE'), + ('MAPI_ALIAS_CODE_RETURN_HIDDEN', '', 'MAPI_ALIAS_CODE_RETURN'), + # dynamic entries + ('MAPI_DYNAMIC_ENTRY', '(ret, name, params)', ''), + ] + undefs = [d[0] for d in defs] + + print '#if defined(MAPI_ABI_ENTRY) || defined(MAPI_ABI_ENTRY_HIDDEN)' + print + for d in defs: + print '#ifndef %s' % (d[0]) + if d[2]: + print '#define %s%s %s' % d + else: + print '#define %s%s' % d[:2] + + print '#endif' + print + + print '/* see MAPI_TMP_TABLE */' + for ent in self.entries: + print '#define MAPI_SLOT_%s %d' % (ent.name, ent.slot) + print + print '/* see MAPI_TMP_PUBLIC_STUBS */' + for ent in self.entries: + print '#define MAPI_POOL_%s %d' % (ent.name, pool_offsets[ent]) + print + + # define macros that generate code + for ent in self.entries: + self.output_entry(ent) + print + dynamics = abi_dynamics() + for ent in dynamics: + self.output_entry(ent) + print + + for ent in self.entries: + print '#undef MAPI_SLOT_%s' % (ent.name) + for ent in self.entries: + print '#undef MAPI_POOL_%s' % (ent.name) + print + print '#endif /* defined(MAPI_ABI_ENTRY) || defined(MAPI_ABI_ENTRY_HIDDEN) */' + print + + self._add_undefs(undefs) + + def _get_string_pool(self): + """Get the string pool.""" + pool = [] + offsets = {} + + count = 0 + for ent in self.entries: + offsets[ent] = count + pool.append(ent.name + '\\0') + count += len(ent.name) + 1 + + return (pool, offsets) + + def output_sorted_indices(self): + entry_index_pairs = [] + for i in xrange(len(self.entries)): + entry_index_pairs.append((self.entries[i], i)) + entry_index_pairs.sort(lambda x, y: cmp(x[0].name, y[0].name)) + + print '/* see MAPI_TMP_PUBLIC_STUBS */' + print '#ifdef MAPI_ABI_SORTED_INDICES' + print + print 'static const int MAPI_ABI_SORTED_INDICES[] = {' + for ent, idx in entry_index_pairs: + print ' %d, /* %s */' % (idx, ent.name) + print ' -1' + print '};' + print + print '#endif /* MAPI_ABI_SORTED_INDICES */' + print + + self._add_undefs(['MAPI_ABI_SORTED_INDICES']) + + def output_defines(self): + print '/* ABI defines */' + print '#ifdef MAPI_ABI_DEFINES' + print '#include "%s"' % (self.options.include) + print '#endif /* MAPI_ABI_DEFINES */' + print + + self._add_undefs(['MAPI_ABI_DEFINES']) + + def output(self): + pool, pool_offsets = self._get_string_pool() + + self.output_header() + self.output_defines() + self.output_entries(pool_offsets) + self.output_sorted_indices() + self.output_footer() + +def parse_args(): + parser = OptionParser(usage='usage: %prog [options] <filename>') + parser.add_option('-i', '--include', dest='include', + help='include the header for API defines') + + options, args = parser.parse_args() + if not args or not options.include: + parser.print_help() + sys.exit(1) + + return (args[0], options) + +def main(): + filename, options = parse_args() + + entries = abi_parse(filename) + printer = ABIPrinter(entries, options) + printer.output() + +if __name__ == '__main__': + main() diff --git a/mesalib/src/mapi/mapi/mapi_tmp.h b/mesalib/src/mapi/mapi/mapi_tmp.h new file mode 100644 index 000000000..79beca47d --- /dev/null +++ b/mesalib/src/mapi/mapi/mapi_tmp.h @@ -0,0 +1,211 @@ +/* + * Mesa 3-D graphics library + * Version: 7.9 + * + * Copyright (C) 2010 LunarG Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Chia-I Wu <olv@lunarg.com> + */ + +#include "u_macros.h" + +#ifndef MAPI_ABI_HEADER +#error "MAPI_ABI_HEADER must be defined" +#endif + + +/** + * Get API defines. + */ +#ifdef MAPI_TMP_DEFINES +# define MAPI_ABI_DEFINES +# include MAPI_ABI_HEADER + +#ifndef MAPI_ABI_PREFIX +#error "MAPI_ABI_PREFIX must be defined" +#endif +#ifndef MAPI_ABI_PUBLIC +#error "MAPI_ABI_PUBLIC must be defined" +#endif +#ifndef MAPI_ABI_ATTR +#error "MAPI_ABI_ATTR must be defined" +#endif + +#undef MAPI_TMP_DEFINES +#endif /* MAPI_TMP_DEFINES */ + + +/** + * Generate fields of struct mapi_table. + */ +#ifdef MAPI_TMP_TABLE +# define MAPI_ABI_ENTRY(ret, name, params) \ + ret (MAPI_ABI_ATTR *name) params; +# define MAPI_DYNAMIC_ENTRY(ret, name, params) \ + ret (MAPI_ABI_ATTR *name) params; +# include MAPI_ABI_HEADER +#undef MAPI_TMP_TABLE +#endif /* MAPI_TMP_TABLE */ + + +/** + * Declare public entries. + */ +#ifdef MAPI_TMP_PUBLIC_DECLARES +# define MAPI_ABI_ENTRY(ret, name, params) \ + MAPI_ABI_PUBLIC ret MAPI_ABI_ATTR U_CONCAT(MAPI_ABI_PREFIX, name) params; +# define MAPI_ALIAS_ENTRY(alias, ret, name, params) \ + MAPI_ABI_ENTRY(ret, name, params); +# define MAPI_ABI_ENTRY_HIDDEN(ret, name, params) \ + HIDDEN ret MAPI_ABI_ATTR U_CONCAT(MAPI_ABI_PREFIX, name) params; +# define MAPI_ALIAS_ENTRY_HIDDEN(alias, ret, name, params) \ + MAPI_ABI_ENTRY_HIDDEN(ret, name, params) +# include MAPI_ABI_HEADER +#undef MAPI_TMP_PUBLIC_DECLARES +#endif /* MAPI_TMP_PUBLIC_DECLARES */ + + +/** + * Generate string pool and public stubs. + */ +#ifdef MAPI_TMP_PUBLIC_STUBS +/* define the string pool */ +static const char public_string_pool[] = +# define MAPI_ABI_ENTRY(ret, name, params) \ + U_STRINGIFY(name) "\0" +# define MAPI_ALIAS_ENTRY(alias, ret, name, params) \ + MAPI_ABI_ENTRY(ret, name, params) +# include MAPI_ABI_HEADER + ; +/* define public_sorted_indices */ +# define MAPI_ABI_SORTED_INDICES public_sorted_indices +# include MAPI_ABI_HEADER + +/* define public_stubs */ +static const struct mapi_stub public_stubs[] = { +# define MAPI_ABI_ENTRY(ret, name, params) \ + { (mapi_func) U_CONCAT(MAPI_ABI_PREFIX, name), \ + MAPI_SLOT_ ## name, (void *) MAPI_POOL_ ## name }, +# define MAPI_ALIAS_ENTRY(alias, ret, name, params) \ + MAPI_ABI_ENTRY(ret, name, params) +# include MAPI_ABI_HEADER + { NULL, -1, (void *) -1 } +}; + +#undef MAPI_TMP_PUBLIC_STUBS +#endif /* MAPI_TMP_PUBLIC_STUBS */ + + +/** + * Generate public entries. + */ +#ifdef MAPI_TMP_PUBLIC_ENTRIES +# define MAPI_ABI_ENTRY(ret, name, params) \ + ret MAPI_ABI_ATTR U_CONCAT(MAPI_ABI_PREFIX, name) params +# define MAPI_ABI_CODE(ret, name, args) \ + { \ + const struct mapi_table *tbl = u_current_get(); \ + tbl->name args; \ + } +# define MAPI_ABI_CODE_RETURN(ret, name, args) \ + { \ + const struct mapi_table *tbl = u_current_get(); \ + return tbl->name args; \ + } +# define MAPI_ALIAS_ENTRY(alias, ret, name, params) \ + MAPI_ABI_ENTRY(ret, name, params) +# define MAPI_ALIAS_CODE(alias, ret, name, args) \ + MAPI_ABI_CODE(ret, alias, args) +# define MAPI_ALIAS_CODE_RETURN(alias, ret, name, args) \ + MAPI_ABI_CODE_RETURN(ret, alias, args) +# include MAPI_ABI_HEADER +#undef MAPI_TMP_PUBLIC_ENTRIES +#endif /* MAPI_TMP_PUBLIC_ENTRIES */ + + +/** + * Generate noop entries. + */ +#ifdef MAPI_TMP_NOOP_ARRAY +#ifdef DEBUG +# define MAPI_ABI_ENTRY(ret, name, params) \ + static ret MAPI_ABI_ATTR U_CONCAT(noop_, name) params +# define MAPI_ABI_CODE(ret, name, args) \ + { \ + noop_warn(U_CONCAT_STR(MAPI_ABI_PREFIX, name)); \ + } +# define MAPI_ABI_CODE_RETURN(ret, name, args) \ + { \ + noop_warn(U_CONCAT_STR(MAPI_ABI_PREFIX, name)); \ + return (ret) 0; \ + } +# include MAPI_ABI_HEADER + +/* define the noop function array that may be casted to mapi_table */ +const mapi_func table_noop_array[] = { +# define MAPI_ABI_ENTRY(ret, name, params) \ + (mapi_func) U_CONCAT(noop_, name), +# define MAPI_DYNAMIC_ENTRY(ret, name, params) \ + (mapi_func) noop_generic, +# include MAPI_ABI_HEADER + (mapi_func) noop_generic +}; + +#else /* DEBUG */ + +const mapi_func table_noop_array[] = { +# define MAPI_ABI_ENTRY(ret, name, params) \ + (mapi_func) noop_generic, +# define MAPI_DYNAMIC_ENTRY(ret, name, params) \ + (mapi_func) noop_generic, +# include MAPI_ABI_HEADER + (mapi_func) noop_generic +}; + +#endif /* DEBUG */ +#undef MAPI_TMP_NOOP_ARRAY +#endif /* MAPI_TMP_NOOP_ARRAY */ + + +#ifdef MAPI_TMP_STUB_ASM_GCC +# define STUB_ASM_ALIAS(func, to) \ + ".globl " func "\n" \ + ".set " func ", " to +# define STUB_ASM_HIDE(func) \ + ".hidden " func + +# define MAPI_ABI_ENTRY(ret, name, params) \ + __asm__(STUB_ASM_ENTRY(U_CONCAT_STR(MAPI_ABI_PREFIX, name))); +# define MAPI_ABI_CODE(ret, name, args) \ + __asm__(STUB_ASM_CODE(U_STRINGIFY(MAPI_SLOT_ ## name))); +# define MAPI_ALIAS_ENTRY(alias, ret, name, params) \ + __asm__(STUB_ASM_ALIAS(U_CONCAT_STR(MAPI_ABI_PREFIX, name), \ + U_CONCAT_STR(MAPI_ABI_PREFIX, alias))); +# define MAPI_ABI_ENTRY_HIDDEN(ret, name, params) \ + __asm__(STUB_ASM_HIDE(U_CONCAT_STR(MAPI_ABI_PREFIX, name))); \ + MAPI_ABI_ENTRY(ret, name, params); +# define MAPI_ALIAS_ENTRY_HIDDEN(alias, ret, name, params) \ + __asm__(STUB_ASM_HIDE(U_CONCAT_STR(MAPI_ABI_PREFIX, name))); \ + MAPI_ALIAS_ENTRY(alias, ret, name, params); +# include MAPI_ABI_HEADER +#undef MAPI_TMP_STUB_ASM_GCC +#endif /* MAPI_TMP_STUB_ASM_GCC */ diff --git a/mesalib/src/mapi/mapi/sources.mak b/mesalib/src/mapi/mapi/sources.mak new file mode 100644 index 000000000..5f327f3df --- /dev/null +++ b/mesalib/src/mapi/mapi/sources.mak @@ -0,0 +1,19 @@ +# src/mapi/mapi/sources.mak +# +# When MAPI_GLAPI_CURRENT is defined, MAPI_GLAPI_SOURCES can be built without +# MAPI_SOURCES and it is used by glapi. +# +# Otherwise, MAPI_ABI_HEADER must be defined. It should expand to the header +# generated by mapi_abi.py. + +MAPI_GLAPI_SOURCES = \ + u_current.c \ + u_execmem.c \ + u_thread.c + +MAPI_SOURCES = \ + entry.c \ + mapi.c \ + stub.c \ + table.c \ + $(MAPI_GLAPI_SOURCES) diff --git a/mesalib/src/mapi/mapi/stub.c b/mesalib/src/mapi/mapi/stub.c new file mode 100644 index 000000000..8ceaec313 --- /dev/null +++ b/mesalib/src/mapi/mapi/stub.c @@ -0,0 +1,180 @@ +/* + * Mesa 3-D graphics library + * Version: 7.9 + * + * Copyright (C) 2010 LunarG Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Chia-I Wu <olv@lunarg.com> + */ + +#include <stdlib.h> +#include <stddef.h> /* for offsetof */ +#include <string.h> +#include <assert.h> + +#include "u_current.h" +#include "u_thread.h" +#include "entry.h" +#include "stub.h" +#include "table.h" + +#define MAPI_TABLE_FIRST_DYNAMIC \ + (offsetof(struct mapi_table, dynamic0) / sizeof(mapi_func)) +#define MAPI_TABLE_NUM_DYNAMIC \ + ((offsetof(struct mapi_table, last) - \ + offsetof(struct mapi_table, dynamic0)) / sizeof(mapi_func)) +#define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0])) + +/* + * This will define public_string_pool, public_sorted_indices, and + * public_stubs. + */ +#define MAPI_TMP_PUBLIC_STUBS +#include "mapi_tmp.h" + +static struct mapi_stub dynamic_stubs[MAPI_TABLE_NUM_DYNAMIC]; +static int num_dynamic_stubs; +static int next_dynamic_slot = MAPI_TABLE_FIRST_DYNAMIC; + +void +stub_init_once(void) +{ +#ifdef PTHREADS + static pthread_once_t once = PTHREAD_ONCE_INIT; + pthread_once(&once, entry_patch_public); +#else + static int first = 1; + if (first) { + first = 0; + entry_patch_public(); + } +#endif +} + +static int +stub_compare(const void *key, const void *elem) +{ + const char *name = (const char *) key; + const int *index = (const int *) elem; + const struct mapi_stub *stub; + const char *stub_name; + + stub = &public_stubs[*index]; + stub_name = &public_string_pool[(unsigned long) stub->name]; + + return strcmp(name, stub_name); +} + +/** + * Return the public stub with the given name. + */ +const struct mapi_stub * +stub_find_public(const char *name) +{ + const int *index; + + index = (const int *) bsearch(name, public_sorted_indices, + ARRAY_SIZE(public_sorted_indices) - 1, + sizeof(public_sorted_indices[0]), stub_compare); + + return (index) ? &public_stubs[*index] : NULL; +} + +/** + * Add a dynamic stub. + */ +static struct mapi_stub * +stub_add_dynamic(const char *name) +{ + struct mapi_stub *stub; + int idx; + + idx = num_dynamic_stubs; + if (idx >= MAPI_TABLE_NUM_DYNAMIC) + return NULL; + + stub = &dynamic_stubs[idx]; + + /* dispatch to mapi_table->last, which is always no-op */ + stub->addr = + entry_generate(MAPI_TABLE_FIRST_DYNAMIC + MAPI_TABLE_NUM_DYNAMIC); + if (!stub->addr) + return NULL; + + stub->name = (const void *) name; + /* to be fixed later */ + stub->slot = -1; + + num_dynamic_stubs = idx + 1; + + return stub; +} + +/** + * Return the dynamic stub with the given name. If no such stub exists and + * generate is true, a new stub is generated. + */ +struct mapi_stub * +stub_find_dynamic(const char *name, int generate) +{ + u_mutex_declare_static(dynamic_mutex); + struct mapi_stub *stub = NULL; + int count, i; + + u_mutex_lock(dynamic_mutex); + + if (generate) + assert(!stub_find_public(name)); + + count = num_dynamic_stubs; + for (i = 0; i < count; i++) { + if (strcmp(name, (const char *) dynamic_stubs[i].name) == 0) { + stub = &dynamic_stubs[i]; + break; + } + } + + /* generate a dynamic stub */ + if (generate && !stub) + stub = stub_add_dynamic(name); + + u_mutex_unlock(dynamic_mutex); + + return stub; +} + +void +stub_fix_dynamic(struct mapi_stub *stub, const struct mapi_stub *alias) +{ + int slot; + + if (stub->slot >= 0) + return; + + if (alias) + slot = alias->slot; + else + slot = next_dynamic_slot++; + + entry_patch(stub->addr, slot); + stub->slot = slot; +} diff --git a/mesalib/src/mapi/mapi/stub.h b/mesalib/src/mapi/mapi/stub.h new file mode 100644 index 000000000..c7e194cf4 --- /dev/null +++ b/mesalib/src/mapi/mapi/stub.h @@ -0,0 +1,52 @@ +/* + * Mesa 3-D graphics library + * Version: 7.9 + * + * Copyright (C) 2010 LunarG Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Chia-I Wu <olv@lunarg.com> + */ + +#ifndef _STUB_H_ +#define _STUB_H_ + +typedef void (*mapi_func)(void); + +struct mapi_stub { + mapi_func addr; + int slot; + const void *name; +}; + +void +stub_init_once(void); + +const struct mapi_stub * +stub_find_public(const char *name); + +struct mapi_stub * +stub_find_dynamic(const char *name, int generate); + +void +stub_fix_dynamic(struct mapi_stub *stub, const struct mapi_stub *alias); + +#endif /* _STUB_H_ */ diff --git a/mesalib/src/mapi/mapi/table.c b/mesalib/src/mapi/mapi/table.c new file mode 100644 index 000000000..8f4f700b9 --- /dev/null +++ b/mesalib/src/mapi/mapi/table.c @@ -0,0 +1,56 @@ +/* + * Mesa 3-D graphics library + * Version: 7.9 + * + * Copyright (C) 2010 LunarG Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Chia-I Wu <olv@lunarg.com> + */ + +#include <stdlib.h> +#include <stdio.h> + +#include "stub.h" +#include "table.h" + +static void +noop_warn(const char *name) +{ + static int debug = -1; + + if (debug < 0) + debug = (getenv("MESA_DEBUG") || getenv("LIBGL_DEBUG")); + + if (debug) + fprintf(stderr, "%s is no-op", name); +} + +static int +noop_generic(void) +{ + noop_warn("function"); + return 0; +} + +/* define noop_array */ +#define MAPI_TMP_NOOP_ARRAY +#include "mapi_tmp.h" diff --git a/mesalib/src/mapi/mapi/table.h b/mesalib/src/mapi/mapi/table.h new file mode 100644 index 000000000..48c99018a --- /dev/null +++ b/mesalib/src/mapi/mapi/table.h @@ -0,0 +1,76 @@ +/* + * Mesa 3-D graphics library + * Version: 7.9 + * + * Copyright (C) 2010 LunarG Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Chia-I Wu <olv@lunarg.com> + */ + +#ifndef _TABLE_H_ +#define _TABLE_H_ + +#include "u_compiler.h" +#include "stub.h" + +#define MAPI_TMP_DEFINES +#include "mapi_tmp.h" + +struct mapi_table { +#define MAPI_TMP_TABLE +#include "mapi_tmp.h" + mapi_func last; +}; + +extern const mapi_func table_noop_array[]; + +/** + * Get the no-op dispatch table. + */ +static INLINE const struct mapi_table * +table_get_noop(void) +{ + return (const struct mapi_table *) table_noop_array; +} + +/** + * Update the dispatch table to dispatch a stub to the given function. + */ +static INLINE void +table_set_func(struct mapi_table *tbl, + const struct mapi_stub *stub, mapi_func func) +{ + mapi_func *funcs = (mapi_func *) tbl; + funcs[stub->slot] = func; +} + +/** + * Return the dispatched function of a stub. + */ +static INLINE mapi_func +table_get_func(const struct mapi_table *tbl, const struct mapi_stub *stub) +{ + const mapi_func *funcs = (const mapi_func *) tbl; + return funcs[stub->slot]; +} + +#endif /* _TABLE_H_ */ diff --git a/mesalib/src/mapi/mapi/u_compiler.h b/mesalib/src/mapi/mapi/u_compiler.h new file mode 100644 index 000000000..f1752d16f --- /dev/null +++ b/mesalib/src/mapi/mapi/u_compiler.h @@ -0,0 +1,48 @@ +#ifndef _U_COMPILER_H_ +#define _U_COMPILER_H_ + +/* Function inlining */ +#ifndef INLINE +# ifdef __cplusplus +# define INLINE inline +# elif defined(__GNUC__) +# define INLINE __inline__ +# elif defined(_MSC_VER) +# define INLINE __inline +# elif defined(__ICL) +# define INLINE __inline +# elif defined(__INTEL_COMPILER) +# define INLINE inline +# elif defined(__WATCOMC__) && (__WATCOMC__ >= 1100) +# define INLINE __inline +# elif defined(__SUNPRO_C) && defined(__C99FEATURES__) +# define INLINE inline +# elif (__STDC_VERSION__ >= 199901L) /* C99 */ +# define INLINE inline +# else +# define INLINE +# endif +#endif + +/* Function visibility */ +#ifndef PUBLIC +# if defined(__GNUC__) || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590)) +# define PUBLIC __attribute__((visibility("default"))) +# elif defined(_MSC_VER) +# define PUBLIC __declspec(dllexport) +# else +# define PUBLIC +# endif +#endif + +#ifndef likely +# if defined(__GNUC__) +# define likely(x) __builtin_expect(!!(x), 1) +# define unlikely(x) __builtin_expect(!!(x), 0) +# else +# define likely(x) (x) +# define unlikely(x) (x) +# endif +#endif + +#endif /* _U_COMPILER_H_ */ diff --git a/mesalib/src/mapi/mapi/u_current.c b/mesalib/src/mapi/mapi/u_current.c new file mode 100644 index 000000000..ed9ccfe22 --- /dev/null +++ b/mesalib/src/mapi/mapi/u_current.c @@ -0,0 +1,277 @@ +/* + * Mesa 3-D graphics library + * Version: 7.1 + * + * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +/* + * This file manages the OpenGL API dispatch layer. + * The dispatch table (struct _glapi_table) is basically just a list + * of function pointers. + * There are functions to set/get the current dispatch table for the + * current thread and to manage registration/dispatch of dynamically + * added extension functions. + * + * It's intended that this file and the other glapi*.[ch] files are + * flexible enough to be reused in several places: XFree86, DRI- + * based libGL.so, and perhaps the SGI SI. + * + * NOTE: There are no dependencies on Mesa in this code. + * + * Versions (API changes): + * 2000/02/23 - original version for Mesa 3.3 and XFree86 4.0 + * 2001/01/16 - added dispatch override feature for Mesa 3.5 + * 2002/06/28 - added _glapi_set_warning_func(), Mesa 4.1. + * 2002/10/01 - _glapi_get_proc_address() will now generate new entrypoints + * itself (using offset ~0). _glapi_add_entrypoint() can be + * called afterward and it'll fill in the correct dispatch + * offset. This allows DRI libGL to avoid probing for DRI + * drivers! No changes to the public glapi interface. + */ + +#include "u_current.h" +#include "u_thread.h" + +#ifndef MAPI_GLAPI_CURRENT + +#include "table.h" +#include "stub.h" + +#else + +extern void init_glapi_relocs_once(void); +extern void (*__glapi_noop_table[])(void); + +#define table_noop_array __glapi_noop_table +#define stub_init_once() init_glapi_relocs_once() + +#endif + +/** + * \name Current dispatch and current context control variables + * + * Depending on whether or not multithreading is support, and the type of + * support available, several variables are used to store the current context + * pointer and the current dispatch table pointer. In the non-threaded case, + * the variables \c _glapi_Dispatch and \c _glapi_Context are used for this + * purpose. + * + * In the "normal" threaded case, the variables \c _glapi_Dispatch and + * \c _glapi_Context will be \c NULL if an application is detected as being + * multithreaded. Single-threaded applications will use \c _glapi_Dispatch + * and \c _glapi_Context just like the case without any threading support. + * When \c _glapi_Dispatch and \c _glapi_Context are \c NULL, the thread state + * data \c _gl_DispatchTSD and \c ContextTSD are used. Drivers and the + * static dispatch functions access these variables via \c _glapi_get_dispatch + * and \c _glapi_get_context. + * + * There is a race condition in setting \c _glapi_Dispatch to \c NULL. It is + * possible for the original thread to be setting it at the same instant a new + * thread, perhaps running on a different processor, is clearing it. Because + * of that, \c ThreadSafe, which can only ever be changed to \c GL_TRUE, is + * used to determine whether or not the application is multithreaded. + * + * In the TLS case, the variables \c _glapi_Dispatch and \c _glapi_Context are + * hardcoded to \c NULL. Instead the TLS variables \c _glapi_tls_Dispatch and + * \c _glapi_tls_Context are used. Having \c _glapi_Dispatch and + * \c _glapi_Context be hardcoded to \c NULL maintains binary compatability + * between TLS enabled loaders and non-TLS DRI drivers. + */ +/*@{*/ +#if defined(GLX_USE_TLS) + +__thread struct mapi_table *u_current_table_tls + __attribute__((tls_model("initial-exec"))) + = (struct mapi_table *) table_noop_array; + +__thread void *u_current_user_tls + __attribute__((tls_model("initial-exec"))); + +const struct mapi_table *u_current_table; +const void *u_current_user; + +#else + +struct mapi_table *u_current_table = + (struct mapi_table *) table_noop_array; +void *u_current_user; + +#ifdef THREADS +struct u_tsd u_current_table_tsd; +static struct u_tsd u_current_user_tsd; +static int ThreadSafe; +#endif /* THREADS */ + +#endif /* defined(GLX_USE_TLS) */ +/*@}*/ + + +void +u_current_destroy(void) +{ +#if defined(THREADS) && defined(WIN32_THREADS) + u_tsd_destroy(&u_current_table_tsd); + u_tsd_destroy(&u_current_user_tsd); +#endif +} + + +#if defined(THREADS) && !defined(GLX_USE_TLS) + +static void +u_current_init_tsd(void) +{ + u_tsd_init(&u_current_table_tsd); + u_tsd_init(&u_current_user_tsd); +} + +/** + * Mutex for multithread check. + */ +#ifdef WIN32_THREADS +/* _glthread_DECLARE_STATIC_MUTEX is broken on windows. There will be race! */ +#define CHECK_MULTITHREAD_LOCK() +#define CHECK_MULTITHREAD_UNLOCK() +#else +u_mutex_declare_static(ThreadCheckMutex); +#define CHECK_MULTITHREAD_LOCK() u_mutex_lock(ThreadCheckMutex) +#define CHECK_MULTITHREAD_UNLOCK() u_mutex_unlock(ThreadCheckMutex) +#endif + +/** + * We should call this periodically from a function such as glXMakeCurrent + * in order to test if multiple threads are being used. + */ +void +u_current_init(void) +{ + static unsigned long knownID; + static int firstCall = 1; + + if (ThreadSafe) + return; + + CHECK_MULTITHREAD_LOCK(); + if (firstCall) { + u_current_init_tsd(); + + knownID = u_thread_self(); + firstCall = 0; + } + else if (knownID != u_thread_self()) { + ThreadSafe = 1; + u_current_set_internal(NULL); + u_current_set_user_internal(NULL); + } + CHECK_MULTITHREAD_UNLOCK(); +} + +#else + +void +u_current_init(void) +{ +} + +#endif + + + +/** + * Set the current context pointer for this thread. + * The context pointer is an opaque type which should be cast to + * void from the real context pointer type. + */ +void +u_current_set_user_internal(void *ptr) +{ + u_current_init(); + +#if defined(GLX_USE_TLS) + u_current_user_tls = ptr; +#elif defined(THREADS) + u_tsd_set(&u_current_user_tsd, ptr); + u_current_user = (ThreadSafe) ? NULL : ptr; +#else + u_current_user = ptr; +#endif +} + +/** + * Get the current context pointer for this thread. + * The context pointer is an opaque type which should be cast from + * void to the real context pointer type. + */ +void * +u_current_get_user_internal(void) +{ +#if defined(GLX_USE_TLS) + return u_current_user_tls; +#elif defined(THREADS) + return (ThreadSafe) + ? u_tsd_get(&u_current_user_tsd) + : u_current_user; +#else + return u_current_user; +#endif +} + +/** + * Set the global or per-thread dispatch table pointer. + * If the dispatch parameter is NULL we'll plug in the no-op dispatch + * table (__glapi_noop_table). + */ +void +u_current_set_internal(struct mapi_table *tbl) +{ + u_current_init(); + + stub_init_once(); + + if (!tbl) + tbl = (struct mapi_table *) table_noop_array; + +#if defined(GLX_USE_TLS) + u_current_table_tls = tbl; +#elif defined(THREADS) + u_tsd_set(&u_current_table_tsd, (void *) tbl); + u_current_table = (ThreadSafe) ? NULL : tbl; +#else + u_current_table = tbl; +#endif +} + +/** + * Return pointer to current dispatch table for calling thread. + */ +struct mapi_table * +u_current_get_internal(void) +{ +#if defined(GLX_USE_TLS) + return u_current_table_tls; +#elif defined(THREADS) + return (struct mapi_table *) ((ThreadSafe) ? + u_tsd_get(&u_current_table_tsd) : (void *) u_current_table); +#else + return u_current_table; +#endif +} diff --git a/mesalib/src/mapi/mapi/u_current.h b/mesalib/src/mapi/mapi/u_current.h new file mode 100644 index 000000000..62e54c6c9 --- /dev/null +++ b/mesalib/src/mapi/mapi/u_current.h @@ -0,0 +1,102 @@ +#ifndef _U_CURRENT_H_ +#define _U_CURRENT_H_ + +#ifdef MAPI_GLAPI_CURRENT + +#include "glapi/glapi.h" + +/* ugly renames to match glapi.h */ +#define mapi_table _glapi_table + +#define u_current_table_tls _glapi_tls_Dispatch +#define u_current_user_tls _glapi_tls_Context +#define u_current_table _glapi_Dispatch +#define u_current_user _glapi_Context + +#define u_current_destroy _glapi_destroy_multithread +#define u_current_init _glapi_check_multithread +#define u_current_set_internal _glapi_set_dispatch +#define u_current_get_internal _glapi_get_dispatch +#define u_current_set_user_internal _glapi_set_context +#define u_current_get_user_internal _glapi_get_context + +#define u_current_table_tsd _gl_DispatchTSD + +#else /* MAPI_GLAPI_CURRENT */ + +#include "u_compiler.h" + +struct mapi_table; + +#ifdef GLX_USE_TLS + +extern __thread struct mapi_table *u_current_table_tls + __attribute__((tls_model("initial-exec"))); + +extern __thread void *u_current_user_tls + __attribute__((tls_model("initial-exec"))); + +extern const struct mapi_table *u_current_table; +extern const void *u_current_user; + +#else /* GLX_USE_TLS */ + +extern struct mapi_table *u_current_table; +extern void *u_current_user; + +#endif /* GLX_USE_TLS */ + +void +u_current_init(void); + +void +u_current_destroy(void); + +void +u_current_set_internal(struct mapi_table *tbl); + +struct mapi_table * +u_current_get_internal(void); + +void +u_current_set_user_internal(void *ptr); + +void * +u_current_get_user_internal(void); + +static INLINE void +u_current_set(const struct mapi_table *tbl) +{ + u_current_set_internal((struct mapi_table *) tbl); +} + +static INLINE const struct mapi_table * +u_current_get(void) +{ +#ifdef GLX_USE_TLS + return (const struct mapi_table *) u_current_table_tls; +#else + return (likely(u_current_table) ? + (const struct mapi_table *) u_current_table : u_current_get_internal()); +#endif +} + +static INLINE void +u_current_set_user(void *ptr) +{ + u_current_set_internal(ptr); +} + +static INLINE void * +u_current_get_user(void) +{ +#ifdef GLX_USE_TLS + return u_current_user_tls; +#else + return likely(u_current_user) ? u_current_user : u_current_get_user_internal(); +#endif +} + +#endif /* MAPI_GLAPI_CURRENT */ + +#endif /* _U_CURRENT_H_ */ diff --git a/mesalib/src/mapi/mapi/u_execmem.c b/mesalib/src/mapi/mapi/u_execmem.c new file mode 100644 index 000000000..e5072e06e --- /dev/null +++ b/mesalib/src/mapi/mapi/u_execmem.c @@ -0,0 +1,145 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 1999-2005 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +/** + * \file glapi_execmem.c + * + * Function for allocating executable memory for dispatch stubs. + * + * Copied from main/execmem.c and simplified for dispatch stubs. + */ + + +#include "u_compiler.h" +#include "u_thread.h" +#include "u_execmem.h" + + +#define EXEC_MAP_SIZE (4*1024) + +u_mutex_declare_static(exec_mutex); + +static unsigned int head = 0; + +static unsigned char *exec_mem = (unsigned char *)0; + + +#if defined(__linux__) || defined(__OpenBSD__) || defined(_NetBSD__) || defined(__sun) + +#include <unistd.h> +#include <sys/mman.h> + +#ifdef MESA_SELINUX +#include <selinux/selinux.h> +#endif + + +#ifndef MAP_ANONYMOUS +#define MAP_ANONYMOUS MAP_ANON +#endif + + +/* + * Dispatch stubs are of fixed size and never freed. Thus, we do not need to + * overlay a heap, we just mmap a page and manage through an index. + */ + +static int +init_map(void) +{ +#ifdef MESA_SELINUX + if (is_selinux_enabled()) { + if (!security_get_boolean_active("allow_execmem") || + !security_get_boolean_pending("allow_execmem")) + return 0; + } +#endif + + if (!exec_mem) + exec_mem = mmap(NULL, EXEC_MAP_SIZE, PROT_EXEC | PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + + return (exec_mem != MAP_FAILED); +} + + +#elif defined(_WIN32) + +#include <windows.h> + + +/* + * Avoid Data Execution Prevention. + */ + +static int +init_map(void) +{ + exec_mem = VirtualAlloc(NULL, EXEC_MAP_SIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE); + + return (exec_mem != NULL); +} + + +#else + +#include <stdlib.h> + +static int +init_map(void) +{ + exec_mem = malloc(EXEC_MAP_SIZE); + + return (exec_mem != NULL); +} + + +#endif + +void * +u_execmem_alloc(unsigned int size) +{ + void *addr = NULL; + + u_mutex_lock(exec_mutex); + + if (!init_map()) + goto bail; + + /* free space check, assumes no integer overflow */ + if (head + size > EXEC_MAP_SIZE) + goto bail; + + /* allocation, assumes proper addr and size alignement */ + addr = exec_mem + head; + head += size; + +bail: + u_mutex_unlock(exec_mutex); + + return addr; +} + + diff --git a/mesalib/src/mapi/mapi/u_execmem.h b/mesalib/src/mapi/mapi/u_execmem.h new file mode 100644 index 000000000..13fff8df2 --- /dev/null +++ b/mesalib/src/mapi/mapi/u_execmem.h @@ -0,0 +1,7 @@ +#ifndef _U_EXECMEM_H_ +#define _U_EXECMEM_H_ + +void * +u_execmem_alloc(unsigned int size); + +#endif /* _U_EXECMEM_H_ */ diff --git a/mesalib/src/mapi/mapi/u_macros.h b/mesalib/src/mapi/mapi/u_macros.h new file mode 100644 index 000000000..72345b5f1 --- /dev/null +++ b/mesalib/src/mapi/mapi/u_macros.h @@ -0,0 +1,12 @@ +#ifndef _U_MACROS_ +#define _U_MACROS_ + +#define _U_STRINGIFY(x) #x +#define _U_CONCAT(x, y) x ## y +#define _U_CONCAT_STR(x, y) #x#y + +#define U_STRINGIFY(x) _U_STRINGIFY(x) +#define U_CONCAT(x, y) _U_CONCAT(x, y) +#define U_CONCAT_STR(x, y) _U_CONCAT_STR(x, y) + +#endif /* _U_MACROS_ */ diff --git a/mesalib/src/mapi/mapi/u_thread.c b/mesalib/src/mapi/mapi/u_thread.c new file mode 100644 index 000000000..e0fa64ae0 --- /dev/null +++ b/mesalib/src/mapi/mapi/u_thread.c @@ -0,0 +1,254 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5.1 + * + * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#include <stdio.h> +#include <stdlib.h> +#include "u_compiler.h" +#include "u_thread.h" + + +/* + * This file should still compile even when THREADS is not defined. + * This is to make things easier to deal with on the makefile scene.. + */ +#ifdef THREADS +#include <errno.h> + +/* + * Error messages + */ +#define INIT_TSD_ERROR "_glthread_: failed to allocate key for thread specific data" +#define GET_TSD_ERROR "_glthread_: failed to get thread specific data" +#define SET_TSD_ERROR "_glthread_: thread failed to set thread specific data" + + +/* + * Magic number to determine if a TSD object has been initialized. + * Kind of a hack but there doesn't appear to be a better cross-platform + * solution. + */ +#define INIT_MAGIC 0xff8adc98 + + + +/* + * POSIX Threads -- The best way to go if your platform supports them. + * Solaris >= 2.5 have POSIX threads, IRIX >= 6.4 reportedly + * has them, and many of the free Unixes now have them. + * Be sure to use appropriate -mt or -D_REENTRANT type + * compile flags when building. + */ +#ifdef PTHREADS + +unsigned long +u_thread_self(void) +{ + return (unsigned long) pthread_self(); +} + + +void +u_tsd_init(struct u_tsd *tsd) +{ + if (pthread_key_create(&tsd->key, NULL/*free*/) != 0) { + perror(INIT_TSD_ERROR); + exit(-1); + } + tsd->initMagic = INIT_MAGIC; +} + + +void * +u_tsd_get(struct u_tsd *tsd) +{ + if (tsd->initMagic != (int) INIT_MAGIC) { + u_tsd_init(tsd); + } + return pthread_getspecific(tsd->key); +} + + +void +u_tsd_set(struct u_tsd *tsd, void *ptr) +{ + if (tsd->initMagic != (int) INIT_MAGIC) { + u_tsd_init(tsd); + } + if (pthread_setspecific(tsd->key, ptr) != 0) { + perror(SET_TSD_ERROR); + exit(-1); + } +} + +#endif /* PTHREADS */ + + + +/* + * Win32 Threads. The only available option for Windows 95/NT. + * Be sure that you compile using the Multithreaded runtime, otherwise + * bad things will happen. + */ +#ifdef WIN32_THREADS + +static void InsteadOf_exit(int nCode) +{ + DWORD dwErr = GetLastError(); +} + +unsigned long +u_thread_self(void) +{ + return GetCurrentThreadId(); +} + + +void +u_tsd_init(struct u_tsd *tsd) +{ + tsd->key = TlsAlloc(); + if (tsd->key == TLS_OUT_OF_INDEXES) { + perror(INIT_TSD_ERROR); + InsteadOf_exit(-1); + } + tsd->initMagic = INIT_MAGIC; +} + + +void +u_tsd_destroy(struct u_tsd *tsd) +{ + if (tsd->initMagic != INIT_MAGIC) { + return; + } + TlsFree(tsd->key); + tsd->initMagic = 0x0; +} + + +void * +u_tsd_get(struct u_tsd *tsd) +{ + if (tsd->initMagic != INIT_MAGIC) { + u_tsd_init(tsd); + } + return TlsGetValue(tsd->key); +} + + +void +u_tsd_set(struct u_tsd *tsd, void *ptr) +{ + /* the following code assumes that the struct u_tsd has been initialized + to zero at creation */ + if (tsd->initMagic != INIT_MAGIC) { + u_tsd_init(tsd); + } + if (TlsSetValue(tsd->key, ptr) == 0) { + perror(SET_TSD_ERROR); + InsteadOf_exit(-1); + } +} + +#endif /* WIN32_THREADS */ + +/* + * BeOS threads + */ +#ifdef BEOS_THREADS + +unsigned long +u_thread_self(void) +{ + return (unsigned long) find_thread(NULL); +} + +void +u_tsd_init(struct u_tsd *tsd) +{ + tsd->key = tls_allocate(); + tsd->initMagic = INIT_MAGIC; +} + +void * +u_tsd_get(struct u_tsd *tsd) +{ + if (tsd->initMagic != (int) INIT_MAGIC) { + u_tsd_init(tsd); + } + return tls_get(tsd->key); +} + +void +u_tsd_set(struct u_tsd *tsd, void *ptr) +{ + if (tsd->initMagic != (int) INIT_MAGIC) { + u_tsd_init(tsd); + } + tls_set(tsd->key, ptr); +} + +#endif /* BEOS_THREADS */ + + + +#else /* THREADS */ + + +/* + * no-op functions + */ + +unsigned long +_glthread_GetID(void) +{ + return 0; +} + + +void +u_tsd_init(struct u_tsd *tsd) +{ + (void) tsd; +} + + +void * +u_tsd_get(struct u_tsd *tsd) +{ + (void) tsd; + return NULL; +} + + +void +u_tsd_set(struct u_tsd *tsd, void *ptr) +{ + (void) tsd; + (void) ptr; +} + + +#endif /* THREADS */ diff --git a/mesalib/src/mapi/mapi/u_thread.h b/mesalib/src/mapi/mapi/u_thread.h new file mode 100644 index 000000000..b4487a340 --- /dev/null +++ b/mesalib/src/mapi/mapi/u_thread.h @@ -0,0 +1,201 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5.2 + * + * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +/* + * Thread support for gl dispatch. + * + * Initial version by John Stone (j.stone@acm.org) (johns@cs.umr.edu) + * and Christoph Poliwoda (poliwoda@volumegraphics.com) + * Revised by Keith Whitwell + * Adapted for new gl dispatcher by Brian Paul + * Modified for use in mapi by Chia-I Wu + */ + +/* + * If this file is accidentally included by a non-threaded build, + * it should not cause the build to fail, or otherwise cause problems. + * In general, it should only be included when needed however. + */ + +#ifndef _U_THREAD_H_ +#define _U_THREAD_H_ + +#include "u_compiler.h" + +#if defined(PTHREADS) || defined(WIN32_THREADS) || defined(BEOS_THREADS) +#ifndef THREADS +#define THREADS +#endif +#endif + +/* + * POSIX threads. This should be your choice in the Unix world + * whenever possible. When building with POSIX threads, be sure + * to enable any compiler flags which will cause the MT-safe + * libc (if one exists) to be used when linking, as well as any + * header macros for MT-safe errno, etc. For Solaris, this is the -mt + * compiler flag. On Solaris with gcc, use -D_REENTRANT to enable + * proper compiling for MT-safe libc etc. + */ +#if defined(PTHREADS) +#include <pthread.h> /* POSIX threads headers */ + +struct u_tsd { + pthread_key_t key; + int initMagic; +}; + +typedef pthread_mutex_t u_mutex; + +#define u_mutex_declare_static(name) \ + static u_mutex name = PTHREAD_MUTEX_INITIALIZER + +#define u_mutex_init(name) pthread_mutex_init(&(name), NULL) +#define u_mutex_destroy(name) pthread_mutex_destroy(&(name)) +#define u_mutex_lock(name) (void) pthread_mutex_lock(&(name)) +#define u_mutex_unlock(name) (void) pthread_mutex_unlock(&(name)) + +#endif /* PTHREADS */ + + +/* + * Windows threads. Should work with Windows NT and 95. + * IMPORTANT: Link with multithreaded runtime library when THREADS are + * used! + */ +#ifdef WIN32_THREADS +#include <windows.h> + +struct u_tsd { + DWORD key; + int initMagic; +}; + +typedef CRITICAL_SECTION u_mutex; + +/* http://locklessinc.com/articles/pthreads_on_windows/ */ +#define u_mutex_declare_static(name) \ + /* static */ u_mutex name = {(void*)-1, -1, 0, 0, 0, 0} + +#define u_mutex_init(name) InitializeCriticalSection(&name) +#define u_mutex_destroy(name) DeleteCriticalSection(&name) +#define u_mutex_lock(name) EnterCriticalSection(&name) +#define u_mutex_unlock(name) LeaveCriticalSection(&name) + +#endif /* WIN32_THREADS */ + + +/* + * BeOS threads. R5.x required. + */ +#ifdef BEOS_THREADS + +/* Problem with OS.h and this file on haiku */ +#ifndef __HAIKU__ +#include <kernel/OS.h> +#endif + +#include <support/TLS.h> + +/* The only two typedefs required here + * this is cause of the OS.h problem + */ +#ifdef __HAIKU__ +typedef int32 thread_id; +typedef int32 sem_id; +#endif + +struct u_tsd { + int32 key; + int initMagic; +}; + +/* Use Benaphore, aka speeder semaphore */ +typedef struct { + int32 lock; + sem_id sem; +} benaphore; +typedef benaphore u_mutex; + +#define u_mutex_declare_static(name) \ + static u_mutex name = { 0, 0 } + +#define u_mutex_init(name) \ + name.sem = create_sem(0, #name"_benaphore"), \ + name.lock = 0 + +#define u_mutex_destroy(name) \ + delete_sem(name.sem), \ + name.lock = 0 + +#define u_mutex_lock(name) \ + if (name.sem == 0) \ + u_mutex_init(name); \ + if (atomic_add(&(name.lock), 1) >= 1) \ + acquire_sem(name.sem) + +#define u_mutex_unlock(name) \ + if (atomic_add(&(name.lock), -1) > 1) \ + release_sem(name.sem) + +#endif /* BEOS_THREADS */ + + +/* + * THREADS not defined + */ +#ifndef THREADS + +struct u_tsd { + int initMagic; +}; + +typedef unsigned u_mutex; + +#define u_mutex_declare_static(name) static u_mutex name = 0 +#define u_mutex_init(name) (void) name +#define u_mutex_destroy(name) (void) name +#define u_mutex_lock(name) (void) name +#define u_mutex_unlock(name) (void) name + +#endif /* THREADS */ + + +unsigned long +u_thread_self(void); + +void +u_tsd_init(struct u_tsd *tsd); + +void +u_tsd_destroy(struct u_tsd *tsd); /* WIN32 only */ + +void * +u_tsd_get(struct u_tsd *tsd); + +void +u_tsd_set(struct u_tsd *tsd, void *ptr); + +#endif /* _U_THREAD_H_ */ |