mesa/src/mapi/shared-glapi/core.c
Jose Maria Casanova Crespo efc87e0d6a
Some checks are pending
macOS-CI / macOS-CI (dri) (push) Waiting to run
macOS-CI / macOS-CI (xlib) (push) Waiting to run
glapi: import noop_array and public stubs earlier.
After 711fc10ea3 "glapi: merge all shared-glapi source files
into one .c file" the V3D simulator started crashing. After
testing the changes of the merge one by one, it was identified
that previously shared_glapi_mapi_tmp.h was being imported twice
instead of only once as it happens after the merge. Although
the change done in the merge seems to be equivalent it seems
it was breaking the the debug builds.

Here can find an explanation why this problem was affecting debug
builds https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/34363#note_2850196

Fixes: 711fc10ea3 ("glapi: merge all shared-glapi source files into one .c file")
Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/12908
Reviewed-by: Marek Olšák <marek.olsak@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/34363>
2025-04-04 00:18:28 +00:00

284 lines
6.3 KiB
C

/* Copyright (C) 2010 LunarG Inc.
* SPDX-License-Identifier: MIT
*
* Authors:
* Chia-I Wu <olv@lunarg.com>
*/
#include "glapi/glapi.h"
struct mapi_stub {
size_t name_offset;
int slot;
};
/* Implemented in mesa/main/context.c. */
void
_mesa_noop_entrypoint(const char *name);
#define MAPI_TMP_NOOP_ARRAY
#define MAPI_TMP_PUBLIC_STUBS
#include "shared_glapi_mapi_tmp.h"
/* REALLY_INITIAL_EXEC implies __GLIBC__ */
#if defined(USE_X86_ASM) && defined(REALLY_INITIAL_EXEC)
#include "entry_x86_tls.h"
#define MAPI_TMP_STUB_ASM_GCC
#include "shared_glapi_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();
extern char x86_entry_start[] HIDDEN;
extern char x86_entry_end[] HIDDEN;
static inline _glapi_proc
entry_generate_or_patch(int, char *, size_t);
static void
entry_patch_public(void)
{
#ifndef GLX_X86_READONLY_TEXT
char *entry;
int slot = 0;
for (entry = x86_entry_start; entry < x86_entry_end;
entry += X86_ENTRY_SIZE, ++slot)
entry_generate_or_patch(slot, entry, X86_ENTRY_SIZE);
#endif
}
static _glapi_proc
entry_get_public(int slot)
{
return (_glapi_proc) (x86_entry_start + slot * X86_ENTRY_SIZE);
}
static void
entry_patch(_glapi_proc entry, int slot)
{
char *code = (char *) entry;
*((unsigned long *) (code + 8)) = slot * sizeof(_glapi_proc);
}
static inline _glapi_proc
entry_generate_or_patch(int slot, char *code, size_t size)
{
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 */
};
_glapi_proc entry;
if (size < sizeof(code_templ))
return NULL;
memcpy(code, code_templ, sizeof(code_templ));
*((unsigned long *) (code + 2)) = x86_current_tls();
entry = (_glapi_proc) code;
entry_patch(entry, slot);
return entry;
}
#elif defined(USE_X86_64_ASM) && defined(REALLY_INITIAL_EXEC)
#include "entry_x86-64_tls.h"
#define MAPI_TMP_STUB_ASM_GCC
#include "shared_glapi_mapi_tmp.h"
#include <string.h>
static void
entry_patch_public(void)
{
}
extern char
x86_64_entry_start[] HIDDEN;
static _glapi_proc
entry_get_public(int slot)
{
return (_glapi_proc) (x86_64_entry_start + slot * 32);
}
#elif defined(USE_PPC64LE_ASM) && UTIL_ARCH_LITTLE_ENDIAN && defined(REALLY_INITIAL_EXEC)
#include "entry_ppc64le_tls.h"
#define MAPI_TMP_STUB_ASM_GCC
#include "shared_glapi_mapi_tmp.h"
#include <string.h>
static void
entry_patch_public(void)
{
}
extern char
ppc64le_entry_start[] HIDDEN;
static _glapi_proc
entry_get_public(int slot)
{
return (_glapi_proc) (ppc64le_entry_start + slot * PPC64LE_ENTRY_SIZE);
}
#else
/* C version of the public entries */
#define MAPI_TMP_DEFINES
#define MAPI_TMP_PUBLIC_ENTRIES
#include "shared_glapi_mapi_tmp.h"
static void
entry_patch_public(void)
{
}
static _glapi_proc
entry_get_public(int slot)
{
return public_entries[slot];
}
#endif /* asm */
/* Current dispatch and current context variables */
__THREAD_INITIAL_EXEC struct _glapi_table *_mesa_glapi_tls_Dispatch
= (struct _glapi_table *)table_noop_array;
__THREAD_INITIAL_EXEC void *_mesa_glapi_tls_Context;
static int
stub_compare(const void *key, const void *elem)
{
const char *name = (const char *)key;
const struct mapi_stub *stub = (const struct mapi_stub *)elem;
return strcmp(name, &public_string_pool[stub->name_offset]);
}
/**
* Return size of dispatch table struct as number of functions (or
* slots).
*/
unsigned
_mesa_glapi_get_dispatch_table_size(void)
{
return _gloffset_COUNT;
}
static const struct mapi_stub *
_glapi_get_stub(const char *name)
{
if (!name || name[0] != 'g' || name[1] != 'l')
return NULL;
return (const struct mapi_stub *)
bsearch(name + 2, public_stubs, ARRAY_SIZE(public_stubs),
sizeof(public_stubs[0]), stub_compare);
}
/**
* Return offset of entrypoint for named function within dispatch table.
*/
int
_mesa_glapi_get_proc_offset(const char *funcName)
{
const struct mapi_stub *stub = _glapi_get_stub(funcName);
return stub ? stub->slot : -1;
}
/**
* Return pointer to the named function. If the function name isn't found
* in the name of static functions, try generating a new API entrypoint on
* the fly with assembly language.
*/
_glapi_proc
_mesa_glapi_get_proc_address(const char *funcName)
{
const struct mapi_stub *stub = _glapi_get_stub(funcName);
return stub ? entry_get_public(stub->slot) : NULL;
}
/**
* Return the name of the function at the given dispatch offset.
* This is only intended for debugging.
*/
const char *
_glapi_get_proc_name(unsigned offset)
{
for (unsigned i = 0; i < ARRAY_SIZE(public_stubs); ++i) {
if (public_stubs[i].slot == offset)
return &public_string_pool[public_stubs[i].name_offset];
}
return NULL;
}
/** Return pointer to new dispatch table filled with no-op functions */
struct _glapi_table *
_glapi_new_nop_table(void)
{
struct _glapi_table *table = malloc(_gloffset_COUNT * sizeof(_glapi_proc));
if (table)
memcpy(table, table_noop_array, _gloffset_COUNT * sizeof(_glapi_proc));
return table;
}
/**
* 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
_mesa_glapi_set_context(void *ptr)
{
_mesa_glapi_tls_Context = ptr;
}
/**
* 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 *
_mesa_glapi_get_context(void)
{
return _mesa_glapi_tls_Context;
}
/**
* 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
_mesa_glapi_set_dispatch(struct _glapi_table *tbl)
{
static once_flag flag = ONCE_FLAG_INIT;
call_once(&flag, entry_patch_public);
_mesa_glapi_tls_Dispatch =
tbl ? tbl : (struct _glapi_table *)table_noop_array;
}
/**
* Return pointer to current dispatch table for calling thread.
*/
struct _glapi_table *
_mesa_glapi_get_dispatch(void)
{
return _mesa_glapi_tls_Dispatch;
}
#if defined(_WIN32) && defined(_WINDOWS_)
#error "Should not include <windows.h> here"
#endif