-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Ian Romanick wrote:
> Here is my first pass at run-time dispatch generation code for x86-64.
> It's not particularly well tested yet (or I'd just commit it now). I
> wrote a test program that called fill_in_entrypoint with a few different
> parameter signature strings, and I verified that the generated code
> looked correct.
>
> After some discussion on IRC, I've been thinking about how we might make
> run-time dispatch generation work on "hardend" systems. Those systems
> don't allow a memory region to be both writable and executable. We can
> use mprotect to adjust the protections. There are a couple sublte
> problems that need to be overcome to make this really work:
Is there any particular reason why the dispatch generation code lives in
src/mesa/glapi? It is only actually used from libGL, and the rest of
the core libGL code lives in src/glx/x11. I have a patch ready
(attached) the leaves the code in src/mesa/glapi, but I think the end
result will be much cleaner if the generation code lives in either
src/glx/x11 or perhaps a new directory called src/glx/common.
Opinions?
Here's the current patch. It only works (i.e., builds) on x86. The
idea will be that the platform dependent code is selected by only
building the correct C file (e.g., glapi_gen_x86.c, glapi_gen_ppc.c, etc.).
I have verified this works by building the libGL from (patched) sources
without GL_EXT_gpu_program_parameters support and using a driver with
support. The dispatch routines were correctly generated and the
prog_parameters test passed.
This code does not contain any of the discussed work-arounds for case
where an app calls glXGetProcAddress for multiple synonym functions
before the driver gets loaded. That's next.
SHA1SUM:
6d2a54073be7fb11e954c80b3ee934069f13e67d gen_dispatch-200608151524.patch
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2.2 (GNU/Linux)
iD8DBQFE4krqX1gOwKyEAw8RAiEwAJ9lh8gpP5GMR5YobiqSa4OgaqOouwCfVh65
PwofFKW95Gb99CkjNH1wUZ8=
=oxb8
-----END PGP SIGNATURE-----
Index: configs/linux-dri-x86
===================================================================
RCS file: /cvs/mesa/Mesa/configs/linux-dri-x86,v
retrieving revision 1.12
diff -u -d -r1.12 linux-dri-x86
--- configs/linux-dri-x86 12 Sep 2005 15:19:19 -0000 1.12
+++ configs/linux-dri-x86 15 Aug 2006 22:25:44 -0000
@@ -9,7 +9,7 @@
PIC_FLAGS =
# Add -m32 to CFLAGS:
-ARCH_FLAGS = -m32
+ARCH_FLAGS = -m32 -DDYNAMIC_DISPATCH
ASM_FLAGS = -DUSE_X86_ASM -DUSE_MMX_ASM -DUSE_3DNOW_ASM -DUSE_SSE_ASM
ASM_SOURCES = $(X86_SOURCES)
Index: src/mesa/sources
===================================================================
RCS file: /cvs/mesa/Mesa/src/mesa/sources,v
retrieving revision 1.66
diff -u -d -r1.66 sources
--- src/mesa/sources 12 Jun 2006 16:26:29 -0000 1.66
+++ src/mesa/sources 15 Aug 2006 22:25:44 -0000
@@ -65,7 +65,8 @@
GLAPI_SOURCES = \
main/dispatch.c \
glapi/glapi.c \
- glapi/glthread.c
+ glapi/glthread.c \
+ glapi/glapi_gen_x86.c
MATH_SOURCES = \
math/m_debug_clip.c \
Index: src/mesa/glapi/glapi.c
===================================================================
RCS file: /cvs/mesa/Mesa/src/mesa/glapi/glapi.c,v
retrieving revision 1.103
diff -u -d -r1.103 glapi.c
--- src/mesa/glapi/glapi.c 16 Jun 2006 14:50:05 -0000 1.103
+++ src/mesa/glapi/glapi.c 15 Aug 2006 22:25:45 -0000
@@ -54,6 +54,7 @@
#include "glapi.h"
#include "glapioffsets.h"
#include "glapitable.h"
+#include "glapi_gen_common.h"
/***** BEGIN NO-OP DISPATCH *****/
@@ -64,8 +65,9 @@
static void init_glapi_relocs(void);
#endif
-static _glapi_proc generate_entrypoint(GLuint functionOffset);
-static void fill_in_entrypoint_offset(_glapi_proc entrypoint, GLuint offset);
+struct _glapi_function;
+static int generate_dispatch_function(struct _glapi_function *func);
+static void init_glapi_platform(void);
/*
* Enable/disable printing of warning messages.
@@ -525,135 +527,73 @@
static struct _glapi_function ExtEntryTable[MAX_EXTENSION_FUNCS];
static GLuint NumExtEntryPoints = 0;
+struct _glapi_dispatch_factory factory;
-#ifdef USE_SPARC_ASM
-extern void __glapi_sparc_icache_flush(unsigned int *);
+
+static void
+init_glapi_platform(void)
+{
+#ifdef DYNAMIC_DISPATCH
+ factory.next_offset = _gloffset_FIRST_DYNAMIC;
+ _glapi_gen_platform_init(& factory);
#endif
+}
-/**
- * Generate a dispatch function (entrypoint) which jumps through
- * the given slot number (offset) in the current dispatch table.
- * We need assembly language in order to accomplish this.
- */
-static _glapi_proc
-generate_entrypoint(GLuint functionOffset)
+
+static int
+generate_dispatch_function(struct _glapi_function *func)
{
-#if defined(USE_X86_ASM)
- /* 32 is chosen as something of a magic offset. For x86, the dispatch
- * at offset 32 is the first one where the offset in the
- * "jmp OFFSET*4(%eax)" can't be encoded in a single byte.
- */
- const GLubyte * const template_func = gl_dispatch_functions_start
- + (X86_DISPATCH_FUNCTION_SIZE * 32);
- GLubyte * const code = (GLubyte *) malloc( X86_DISPATCH_FUNCTION_SIZE );
+#ifdef DYNAMIC_DISPATCH
+ struct _glapi_dispatch_header *h;
+ unsigned hash;
+ unsigned byte_offset;
- if ( code != NULL ) {
- (void) memcpy( code, template_func, X86_DISPATCH_FUNCTION_SIZE );
- fill_in_entrypoint_offset( (_glapi_proc) code, functionOffset );
- }
+ /* Get a pointer to the dispatch header for the requested function
+ * signature.
+ */
+ hash = (*factory.hash_signature)(func->parameter_signature);
+ h = & factory.header[ hash ];
- return (_glapi_proc) code;
-#elif defined(USE_SPARC_ASM)
-#ifdef __arch64__
- static const unsigned int insn_template[] = {
- 0x05000000, /* sethi %uhi(_glapi_Dispatch), %g2 */
- 0x03000000, /* sethi %hi(_glapi_Dispatch), %g1 */
- 0x8410a000, /* or %g2, %ulo(_glapi_Dispatch), %g2 */
- 0x82106000, /* or %g1, %lo(_glapi_Dispatch), %g1 */
- 0x8528b020, /* sllx %g2, 32, %g2 */
- 0xc2584002, /* ldx [%g1 + %g2], %g1 */
- 0x05000000, /* sethi %hi(8 * glapioffset), %g2 */
- 0x8410a000, /* or %g2, %lo(8 * glapioffset), %g2 */
- 0xc6584002, /* ldx [%g1 + %g2], %g3 */
- 0x81c0c000, /* jmpl %g3, %g0 */
- 0x01000000 /* nop */
- };
-#else
- static const unsigned int insn_template[] = {
- 0x03000000, /* sethi %hi(_glapi_Dispatch), %g1 */
- 0xc2006000, /* ld [%g1 + %lo(_glapi_Dispatch)], %g1 */
- 0xc6006000, /* ld [%g1 + %lo(4*glapioffset)], %g3 */
- 0x81c0c000, /* jmpl %g3, %g0 */
- 0x01000000 /* nop */
- };
-#endif /* __arch64__ */
- unsigned int *code = (unsigned int *) malloc(sizeof(insn_template));
- unsigned long glapi_addr = (unsigned long) &_glapi_Dispatch;
- if (code) {
- memcpy(code, insn_template, sizeof(insn_template));
+ /* If there is no page with available functions, dip into the platform-
+ * specific code and get one!
+ */
+ if (h->current_page == NULL) {
+ int err;
+
+ h->base_dispatch_offset = factory.next_offset;
+ h->current_offset = 0;
-#ifdef __arch64__
- code[0] |= (glapi_addr >> (32 + 10));
- code[1] |= ((glapi_addr & 0xffffffff) >> 10);
- __glapi_sparc_icache_flush(&code[0]);
- code[2] |= ((glapi_addr >> 32) & ((1 << 10) - 1));
- code[3] |= (glapi_addr & ((1 << 10) - 1));
- __glapi_sparc_icache_flush(&code[2]);
- code[6] |= ((functionOffset * 8) >> 10);
- code[7] |= ((functionOffset * 8) & ((1 << 10) - 1));
- __glapi_sparc_icache_flush(&code[6]);
-#else
- code[0] |= (glapi_addr >> 10);
- code[1] |= (glapi_addr & ((1 << 10) - 1));
- __glapi_sparc_icache_flush(&code[0]);
- code[2] |= (functionOffset * 4);
- __glapi_sparc_icache_flush(&code[2]);
-#endif /* __arch64__ */
- }
- return (_glapi_proc) code;
-#else
- (void) functionOffset;
- return NULL;
-#endif /* USE_*_ASM */
-}
+ err = (*factory.get_page)(& factory, h, hash);
+ if (err < 0) {
+ return err;
+ }
+ factory.next_offset += h->functions_per_page;
+ }
-/**
- * This function inserts a new dispatch offset into the assembly language
- * stub that was generated with the preceeding function.
- */
-static void
-fill_in_entrypoint_offset(_glapi_proc entrypoint, GLuint offset)
-{
-#if defined(USE_X86_ASM)
- GLubyte * const code = (GLubyte *) entrypoint;
-#if X86_DISPATCH_FUNCTION_SIZE == 32
- *((unsigned int *)(code + 11)) = 4 * offset;
- *((unsigned int *)(code + 22)) = 4 * offset;
-#elif X86_DISPATCH_FUNCTION_SIZE == 16 && defined( GLX_USE_TLS )
- *((unsigned int *)(code + 8)) = 4 * offset;
-#elif X86_DISPATCH_FUNCTION_SIZE == 16
- *((unsigned int *)(code + 7)) = 4 * offset;
-#else
-# error Invalid X86_DISPATCH_FUNCTION_SIZE!
-#endif
+ byte_offset = h->current_offset * h->bytes_per_function;
-#elif defined(USE_SPARC_ASM)
+ func->dispatch_offset = h->current_offset + h->base_dispatch_offset;
+ func->dispatch_stub = (_glapi_proc)((char *)h->current_page + byte_offset);
- /* XXX this hasn't been tested! */
- unsigned int *code = (unsigned int *) entrypoint;
-#ifdef __arch64__
- code[6] = 0x05000000; /* sethi %hi(8 * glapioffset), %g2 */
- code[7] = 0x8410a000; /* or %g2, %lo(8 * glapioffset), %g2 */
- code[6] |= ((offset * 8) >> 10);
- code[7] |= ((offset * 8) & ((1 << 10) - 1));
- __glapi_sparc_icache_flush(&code[6]);
-#else /* __arch64__ */
- code[2] = 0xc6006000; /* ld [%g1 + %lo(4*glapioffset)], %g3 */
- code[2] |= (offset * 4);
- __glapi_sparc_icache_flush(&code[2]);
-#endif /* __arch64__ */
+ h->current_offset++;
-#else
- /* an unimplemented architecture */
- (void) entrypoint;
- (void) offset;
+ /* If this is the last function on the page, NULL out the page pointer
+ * so that the next call for this signature will create a new page.
+ */
+ if (h->current_offset >= h->functions_per_page) {
+ h->current_page = NULL;
+ }
-#endif /* USE_*_ASM */
+
+ return 0;
+#else
+ return -ENOSYS;
+#endif /* DYNAMIC_DISPATCH */
}
@@ -671,21 +611,31 @@
*/
static struct _glapi_function *
-add_function_name( const char * funcName )
+add_function_name(const char * funcName, const char *signature)
{
struct _glapi_function * entry = NULL;
+#if defined(PTHREADS) || defined(GLX_USE_TLS)
+ static pthread_once_t once_control = PTHREAD_ONCE_INIT;
+ pthread_once(& once_control, init_glapi_platform);
+#else
+ static int once_control = 0;
+
+
+ if (!once_control) {
+ init_glapi_platform();
+ once_control = 1;
+ }
+#endif
if (NumExtEntryPoints < MAX_EXTENSION_FUNCS) {
- _glapi_proc entrypoint = generate_entrypoint(~0);
- if (entrypoint != NULL) {
- entry = & ExtEntryTable[NumExtEntryPoints];
+ ExtEntryTable[NumExtEntryPoints].name = str_dup(funcName);
+ ExtEntryTable[NumExtEntryPoints].parameter_signature =
+ (signature == NULL) ? NULL : str_dup(signature);
- ExtEntryTable[NumExtEntryPoints].name = str_dup(funcName);
- ExtEntryTable[NumExtEntryPoints].parameter_signature = NULL;
- ExtEntryTable[NumExtEntryPoints].dispatch_offset = ~0;
- ExtEntryTable[NumExtEntryPoints].dispatch_stub = entrypoint;
- NumExtEntryPoints++;
- }
+ if (generate_dispatch_function(& ExtEntryTable[NumExtEntryPoints]) == 0) {
+ entry = & ExtEntryTable[NumExtEntryPoints];
+ NumExtEntryPoints++;
+ }
}
return entry;
@@ -743,7 +693,6 @@
_glapi_add_dispatch( const char * const * function_names,
const char * parameter_signature )
{
- static int next_dynamic_offset = _gloffset_FIRST_DYNAMIC;
const char * const real_sig = (parameter_signature != NULL)
? parameter_signature : "";
struct _glapi_function * entry[8];
@@ -786,48 +735,43 @@
for ( j = 0 ; j < NumExtEntryPoints ; j++ ) {
if (strcmp(ExtEntryTable[j].name, function_names[i]) == 0) {
- /* The offset may be ~0 if the function name was added by
- * glXGetProcAddress but never filled in by the driver.
+ /* The parameter_signature will be NULL if the function name was
+ * added by glXGetProcAddress.
*/
- if (ExtEntryTable[j].dispatch_offset != ~0) {
- if (strcmp(real_sig, ExtEntryTable[j].parameter_signature)
- != 0) {
- return -1;
- }
-
- if ( (offset != ~0) && (ExtEntryTable[j].dispatch_offset != offset) ) {
- return -1;
- }
+ if ((ExtEntryTable[j].parameter_signature != NULL)
+ && strcmp(real_sig, ExtEntryTable[j].parameter_signature) != 0) {
+ return -1;
+ }
- offset = ExtEntryTable[j].dispatch_offset;
+ if ((offset != ~0)
+ && (ExtEntryTable[j].dispatch_offset != offset)) {
+ return -1;
}
-
+
+ offset = ExtEntryTable[j].dispatch_offset;
entry[i] = & ExtEntryTable[j];
break;
}
}
}
- if (offset == ~0) {
- offset = next_dynamic_offset;
- next_dynamic_offset++;
- }
for ( i = 0 ; function_names[i] != NULL ; i++ ) {
if (! is_static[i] ) {
if (entry[i] == NULL) {
- entry[i] = add_function_name( function_names[i] );
+ entry[i] = add_function_name(function_names[i], real_sig);
if (entry[i] == NULL) {
/* FIXME: Possible memory leak here.
*/
return -1;
}
- }
- entry[i]->parameter_signature = str_dup(real_sig);
- fill_in_entrypoint_offset(entry[i]->dispatch_stub, offset);
- entry[i]->dispatch_offset = offset;
+ offset = entry[i]->dispatch_offset;
+ }
+ else if (entry[i]->parameter_signature == NULL) {
+ entry[i]->parameter_signature = str_dup(real_sig);
+ }
}
}
@@ -889,7 +833,7 @@
}
#endif /* !defined( XFree86Server ) */
- entry = add_function_name(funcName);
+ entry = add_function_name(funcName, NULL);
return (entry == NULL) ? NULL : entry->dispatch_stub;
}
Index: src/mesa/glapi/glapi_gen_SPARC.c
===================================================================
RCS file: src/mesa/glapi/glapi_gen_SPARC.c
diff -N src/mesa/glapi/glapi_gen_SPARC.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/mesa/glapi/glapi_gen_SPARC.c 15 Aug 2006 22:25:45 -0000
@@ -0,0 +1,151 @@
+/*
+ * (C) Copyright IBM Corporation 2006
+ * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
+ * 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
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, 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 (including the next
+ * paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * COPYRIGHT HOLDERS, AUTHORS, AND/OR THEIR SUPPLIERS 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_gen_SPARC.c
+ * SPARC platform dependent code for dispatch generation.
+ *
+ * \author Brian Paul
+ * \author Ian Romanick <[EMAIL PROTECTED]>
+ */
+
+extern void __glapi_sparc_icache_flush(unsigned int *);
+
+#ifdef __arch64__
+static const unsigned int insn_template[] = {
+ 0x05000000, /* sethi %uhi(_glapi_Dispatch), %g2 */
+ 0x03000000, /* sethi %hi(_glapi_Dispatch), %g1 */
+ 0x8410a000, /* or %g2, %ulo(_glapi_Dispatch), %g2 */
+ 0x82106000, /* or %g1, %lo(_glapi_Dispatch), %g1 */
+ 0x8528b020, /* sllx %g2, 32, %g2 */
+ 0xc2584002, /* ldx [%g1 + %g2], %g1 */
+ 0x05000000, /* sethi %hi(8 * glapioffset), %g2 */
+ 0x8410a000, /* or %g2, %lo(8 * glapioffset), %g2 */
+ 0xc6584002, /* ldx [%g1 + %g2], %g3 */
+ 0x81c0c000, /* jmpl %g3, %g0 */
+ 0x01000000 /* nop */
+};
+#else
+static const unsigned int insn_template[] = {
+ 0x03000000, /* sethi %hi(_glapi_Dispatch), %g1 */
+ 0xc2006000, /* ld [%g1 + %lo(_glapi_Dispatch)], %g1 */
+ 0xc6006000, /* ld [%g1 + %lo(4*glapioffset)], %g3 */
+ 0x81c0c000, /* jmpl %g3, %g0 */
+ 0x01000000 /* nop */
+};
+#endif /* __arch64__ */
+
+
+static unsigned
+sparc_hash_signature(const char *signature)
+{
+ (void) signature;
+ return 0;
+}
+
+
+/**
+ * \bug
+ * This code is completely wrong. It's taken directly from glapi.c, but it
+ * doesn't use the proper thread-safe accessors in the generated dispatch
+ * functions.
+ */
+static int
+sparc_get_page(const struct _glapi_dispatch_factory *factory,
+ struct _glapi_dispatch_header *header, unsigned signature_hash)
+{
+ unsigned i;
+ unsigned char *page;
+
+
+ /* There are three distinct steps to this process. First, a single page
+ * is allocated. Then the page is filled with dispatch functions.
+ * Finally, the page is marked as read-only and executable.
+ */
+ page = malloc((factory->page_size * 2) - 1);
+ if (page == NULL) {
+ return -ENOMEM;
+ }
+
+ page = (void *) (((intptr_t)page + (factory->page_size - 1))
+ & ~(factory->page_size - 1));
+
+
+ for (i = 0; i < header->functions_per_page; i++) {
+ unsigned int * const code =
+ (unsigned int *)(page + (i * sizeof(insn_template)));
+ const unsigned offset = header->base_dispatch_offset + i;
+ unsigned long glapi_addr = (unsigned long) &_glapi_Dispatch;
+
+ (void) memcpy(code, insn_template, sizeof(insn_template));
+
+#ifdef __arch64__
+ code[0] |= (glapi_addr >> (32 + 10));
+ code[1] |= ((glapi_addr & 0xffffffff) >> 10);
+ __glapi_sparc_icache_flush(&code[0]);
+ code[2] |= ((glapi_addr >> 32) & ((1 << 10) - 1));
+ code[3] |= (glapi_addr & ((1 << 10) - 1));
+ __glapi_sparc_icache_flush(&code[2]);
+ code[6] |= ((offset * 8) >> 10);
+ code[7] |= ((offset * 8) & ((1 << 10) - 1));
+ __glapi_sparc_icache_flush(&code[6]);
+#else
+ code[0] |= (glapi_addr >> 10);
+ code[1] |= (glapi_addr & ((1 << 10) - 1));
+ __glapi_sparc_icache_flush(&code[0]);
+ code[2] |= (offset * 4);
+ __glapi_sparc_icache_flush(&code[2]);
+#endif /* __arch64__ */
+ }
+
+ if (mprotect(page, factory->page_size, PROT_READ|PROT_EXEC)) {
+ free(page);
+ return -errno;
+ }
+
+ header->current_page = page;
+ return 0;
+}
+
+
+int
+_glapi_gen_platform_init(struct _glapi_dispatch_factory *factory)
+{
+ factory->num_signatures = 1;
+ factory->page_size = getpagesize();
+ factory->hash_signature = sparc_hash_signature;
+ factory->get_page = sparc_get_page;
+
+ factory->header = calloc(1, sizeof(struct _glapi_dispatch_header));
+ if (factory->header == NULL) {
+ return -ENOMEM;
+ }
+
+ factory->header->bytes_per_function = sizeof(insn_template);
+ factory->header->functions_per_page = factory->page_size /
+ factory->header->bytes_per_function;
+
+ return 0;
+}
Index: src/mesa/glapi/glapi_gen_common.h
===================================================================
RCS file: src/mesa/glapi/glapi_gen_common.h
diff -N src/mesa/glapi/glapi_gen_common.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/mesa/glapi/glapi_gen_common.h 15 Aug 2006 22:25:45 -0000
@@ -0,0 +1,143 @@
+/*
+ * (C) Copyright IBM Corporation 2006
+ * 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
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, 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 (including the next
+ * paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * COPYRIGHT HOLDERS, AUTHORS, AND/OR THEIR SUPPLIERS 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.
+ */
+
+#ifndef GLAPI_GEN_COMMON_H
+#define GLAPI_GEN_COMMON_H
+
+/**
+ * \file glapi_gen_common.h
+ * Platform independent structures and prototypes for dispatch generation.
+ *
+ * \author Ian Romanick <[EMAIL PROTECTED]>
+ */
+
+/**
+ * Control structure for generating dispatch functions.
+ *
+ * Each architecture has some fixed number of possible dispatch function
+ * signatures. For each possible signature, there is a page allocated.
+ * This page is initialized with as many dispatch functions as will fit.
+ * These functions are complete, so this implies that dispatch offset for
+ * the functions are assigned at this time.
+ */
+struct _glapi_dispatch_factory {
+ /**
+ * Total number of possible function signatures for this architecture.
+ * For x86, which passes all parameters on the stack, and architectures
+ * that use TLS, this will be 1. For non-TLS x86-64, which has 6
+ * integer registers and 8 floating point registers, this is
+ * (6 + 1) * (8 + 1) = 63.
+ */
+ unsigned num_signatures;
+
+ /**
+ * Size, in bytes, of a single page for this architecture.
+ */
+ unsigned page_size;
+
+ /**
+ * When the next page is created, this is the dispatch offset of the
+ * first function stored on that page.
+ */
+ unsigned next_offset;
+
+ /**
+ * Array of \c ::num_signatures dispatch header structures.
+ */
+ struct _glapi_dispatch_header * header;
+
+ /**
+ * Hash a signature to create an index into \c ::header. If this function
+ * is called via \c glXGetProcAddress, the function signature will not
+ * be known. In that case, \c signature will be \c NULL.
+ *
+ * \param signature Signature string to be hashed.
+ *
+ * \return
+ * An index into the \c ::header array. By definition this must be
+ * less than \c ::num_signatures.
+ */
+ unsigned (*hash_signature)(const char *signature);
+
+ /**
+ * When \c header::current_page is \c NULL, this function is called to
+ * allocate and initialize a fresh page of dispatch functions.
+ *
+ * \param header Pointer to the bin to be refilled.
+ * \param signature Signature index associated with the bin.
+ *
+ * \note
+ * This function assumes that the caller will have properly initialized
+ * \c header::base_dispatch_offset and \c header::current_offset.
+ *
+ * \return
+ * Zero on success or a negative errno value on failure.
+ */
+ int (*get_page)(const struct _glapi_dispatch_factory *factory,
+ struct _glapi_dispatch_header *header,
+ unsigned signature_hash);
+};
+
+
+/**
+ * Bookkeeping structure for an individual dispatch function signature.
+ */
+struct _glapi_dispatch_header {
+ /**
+ * Each of the possible dispatch functions for a given architecture can
+ * have a different size. This will depend, for example, on how many
+ * registers need to be saved and restored around the call to get the
+ * current dispatch pointer. This value stores that size for this
+ * function signature signature.
+ */
+ unsigned bytes_per_function;
+
+ /**
+ * Total number of dispatch functions with this signature that fit in a
+ * single page.
+ */
+ unsigned functions_per_page;
+
+ /**
+ * Dispatch offset of the first function stored in the current page.
+ */
+ unsigned base_dispatch_offset;
+
+ /**
+ * Offset, on the range [0, n-1], of the next dispatch function with this
+ * signature to be returned. n is the number of dispatch functions stored
+ * per page.
+ */
+ unsigned current_offset;
+
+ /**
+ * Base address of the current page. If no page is currently available,
+ * this will be \c NULL.
+ */
+ void * current_page;
+};
+
+extern int _glapi_gen_platform_init(struct _glapi_dispatch_factory *factory);
+
+#endif /* GLAPI_GEN_COMMON_H */
Index: src/mesa/glapi/glapi_gen_x86.c
===================================================================
RCS file: src/mesa/glapi/glapi_gen_x86.c
diff -N src/mesa/glapi/glapi_gen_x86.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/mesa/glapi/glapi_gen_x86.c 15 Aug 2006 22:25:45 -0000
@@ -0,0 +1,149 @@
+/*
+ * (C) Copyright IBM Corporation 2006
+ * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
+ * 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
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, 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 (including the next
+ * paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+ * COPYRIGHT HOLDERS, AUTHORS, AND/OR THEIR SUPPLIERS 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_gen_x86.c
+ * x86 platform dependent code for dispatch generation.
+ *
+ * \author Brian Paul
+ * \author Ian Romanick <[EMAIL PROTECTED]>
+ */
+
+#include <GL/gl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/mman.h>
+
+#include "glapi_gen_common.h"
+
+#if defined(GLX_USE_TLS)
+extern GLubyte gl_dispatch_functions_start[];
+extern GLubyte gl_dispatch_functions_end[];
+extern void *_x86_get_dispatch(void);
+#else
+extern const GLubyte gl_dispatch_functions_start[];
+#endif
+
+#if defined(THREADS) && !defined(GLX_USE_TLS)
+# define X86_DISPATCH_FUNCTION_SIZE 32
+#else
+# define X86_DISPATCH_FUNCTION_SIZE 16
+#endif
+
+static unsigned char insn_template[X86_DISPATCH_FUNCTION_SIZE];
+
+
+static unsigned
+x86_hash_signature(const char *signature)
+{
+ (void) signature;
+ return 0;
+}
+
+
+static int
+x86_get_page(const struct _glapi_dispatch_factory *factory,
+ struct _glapi_dispatch_header *header, unsigned signature_hash)
+
+{
+ unsigned i;
+ unsigned char *page;
+
+
+ /* There are three distinct steps to this process. First, a single page
+ * is allocated. Then the page is filled with dispatch functions.
+ * Finally, the page is marked as read-only and executable.
+ */
+ page = malloc((factory->page_size * 2) - 1);
+ if (page == NULL) {
+ return -ENOMEM;
+ }
+
+ page = (void *) (((intptr_t)page + (factory->page_size - 1))
+ & ~(factory->page_size - 1));
+
+
+ for (i = 0; i < header->functions_per_page; i++) {
+ GLubyte * const code = page + (i * sizeof(insn_template));
+ const unsigned offset = header->base_dispatch_offset + i;
+
+ (void) memcpy(code, insn_template, sizeof(insn_template));
+
+#if X86_DISPATCH_FUNCTION_SIZE == 32
+ *((unsigned int *)(code + 11)) = 4 * offset;
+ *((unsigned int *)(code + 22)) = 4 * offset;
+#elif X86_DISPATCH_FUNCTION_SIZE == 16 && defined( GLX_USE_TLS )
+ *((unsigned int *)(code + 8)) = 4 * offset;
+#elif X86_DISPATCH_FUNCTION_SIZE == 16
+ *((unsigned int *)(code + 7)) = 4 * offset;
+#else
+# error Invalid X86_DISPATCH_FUNCTION_SIZE!
+#endif
+ }
+
+ if (mprotect(page, factory->page_size, PROT_READ|PROT_EXEC) < 0) {
+ free(page);
+ return -errno;
+ }
+
+ header->current_page = page;
+ return 0;
+}
+
+
+int
+_glapi_gen_platform_init(struct _glapi_dispatch_factory *factory)
+{
+ /* 32 is chosen as something of a magic offset. For x86, the dispatch
+ * at offset 32 is the first one where the offset in the
+ * "jmp OFFSET*4(%eax)" can't be encoded in a single byte.
+ */
+ const unsigned char * const template_func = gl_dispatch_functions_start
+ + (X86_DISPATCH_FUNCTION_SIZE * 32);
+
+
+ factory->num_signatures = 1;
+ factory->page_size = getpagesize();
+ factory->hash_signature = x86_hash_signature;
+ factory->get_page = x86_get_page;
+
+ factory->header = calloc(1, sizeof(struct _glapi_dispatch_header));
+ if (factory->header == NULL) {
+ return -ENOMEM;
+ }
+
+ factory->header->bytes_per_function = X86_DISPATCH_FUNCTION_SIZE;
+ factory->header->functions_per_page = factory->page_size /
+ factory->header->bytes_per_function;
+
+
+ (void) memcpy(insn_template, template_func, X86_DISPATCH_FUNCTION_SIZE);
+#ifdef GLX_USE_TLS
+ (void) memcpy(insn_template, _x86_get_dispatch, 6);
+#endif
+ return 0;
+}
-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
Mesa3d-dev mailing list
Mesa3d-dev@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mesa3d-dev