summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukasz Kostyra <l.kostyra@samsung.com>2020-07-23 16:11:40 +0200
committerLukasz Kostyra <l.kostyra@samsung.com>2020-07-27 19:09:26 +0200
commitf98a012c6b2d0760a5ee02c134a3e37b10bc2906 (patch)
tree6d334130aee0483799138e905becd9e62b0ed956
parent552acc5e211eb1a2f1ce160a214211e5f3a2952b (diff)
downloademulator-yagl-f98a012c6b2d0760a5ee02c134a3e37b10bc2906.tar.gz
emulator-yagl-f98a012c6b2d0760a5ee02c134a3e37b10bc2906.tar.bz2
emulator-yagl-f98a012c6b2d0760a5ee02c134a3e37b10bc2906.zip
Implement thread safety when sharing EGL contextsubmit/tizen/20200729.080538accepted/tizen/unified/20200729.165549
- glGen* and associated calls now lock a sharegroup-global mutex. - glGen* and glDeleteObjects host calls flush the transport to ensure resource is created before recording more calls. - Some instances of yagl_host_glDeleteObjects being called were removed because they caused the same assertion to fail - these could remove a texture which was next bound. Change-Id: Iea1b71062f25bc48a6aa583f7074801d416574a8
-rw-r--r--EGL/yagl_egl_calls.c4
-rw-r--r--EGL/yagl_host_egl_calls.c1
-rw-r--r--EGL/yagl_sharegroup.c28
-rw-r--r--EGL/yagl_transport.c1
-rw-r--r--GLES_common/yagl_gles_calls.c62
-rw-r--r--GLES_common/yagl_gles_texture.c4
-rw-r--r--GLES_common/yagl_host_gles_calls.c7
-rw-r--r--GLESv2/yagl_gles2_calls.c24
-rw-r--r--include/yagl_client_context.h1
-rw-r--r--include/yagl_sharegroup.h11
-rw-r--r--include/yagl_transport.h1
11 files changed, 132 insertions, 12 deletions
diff --git a/EGL/yagl_egl_calls.c b/EGL/yagl_egl_calls.c
index cabf163..db484df 100644
--- a/EGL/yagl_egl_calls.c
+++ b/EGL/yagl_egl_calls.c
@@ -1866,11 +1866,15 @@ YAGL_API EGLImageKHR eglCreateImageKHR(EGLDisplay dpy_,
goto out;
}
+ yagl_sharegroup_mutex_lock_if_shared(ctx->client_ctx->sg);
+
image = yagl_get_backend()->create_image_gl_texture_2d(dpy,
ctx,
(yagl_object_name)VOIDP2INT(buffer),
iface);
+ yagl_sharegroup_mutex_unlock_if_shared(ctx->client_ctx->sg);
+
if (!image) {
goto out;
}
diff --git a/EGL/yagl_host_egl_calls.c b/EGL/yagl_host_egl_calls.c
index 766748a..654389b 100644
--- a/EGL/yagl_host_egl_calls.c
+++ b/EGL/yagl_host_egl_calls.c
@@ -497,6 +497,7 @@ EGLBoolean yagl_host_eglCreateImageYAGL(uint32_t texture, yagl_host_handle dpy,
yagl_transport_put_in_EGLint(t, error);
yagl_transport_put_in_EGLBoolean(t, &retval);
yagl_transport_end(t);
+ yagl_transport_flush(t, NULL);
return retval;
}
diff --git a/EGL/yagl_sharegroup.c b/EGL/yagl_sharegroup.c
index 4e35831..45de196 100644
--- a/EGL/yagl_sharegroup.c
+++ b/EGL/yagl_sharegroup.c
@@ -34,6 +34,7 @@
#include "yagl_sharegroup.h"
#include "yagl_object.h"
#include "yagl_malloc.h"
+#include "yagl_utils.h"
static void yagl_sharegroup_destroy(struct yagl_ref *ref)
{
@@ -50,6 +51,8 @@ static void yagl_sharegroup_destroy(struct yagl_ref *ref)
yagl_ref_cleanup(&sg->ref);
+ pthread_mutex_destroy(&sg->mutex);
+
yagl_free(sg);
}
@@ -58,6 +61,8 @@ struct yagl_sharegroup *yagl_sharegroup_create(void)
struct yagl_sharegroup *sg = yagl_malloc0(sizeof(struct yagl_sharegroup));
int i;
+ yagl_mutex_init(&sg->mutex);
+
yagl_ref_init(&sg->ref, &yagl_sharegroup_destroy);
for (i = 0; i < YAGL_NUM_NAMESPACES; ++i) {
@@ -109,3 +114,26 @@ struct yagl_object *yagl_sharegroup_acquire_object(struct yagl_sharegroup *sg,
{
return yagl_namespace_acquire(&sg->namespaces[ns], local_name);
}
+
+static __inline int yagl_sharegroup_is_shared(struct yagl_sharegroup *sg)
+{
+ pthread_mutex_lock(&sg->ref.mutex);
+ int res = (sg->ref.count > 1);
+ pthread_mutex_unlock(&sg->ref.mutex);
+
+ return res;
+}
+
+void yagl_sharegroup_mutex_lock_if_shared(struct yagl_sharegroup *sg)
+{
+ if (yagl_sharegroup_is_shared(sg)) {
+ pthread_mutex_lock(&sg->mutex);
+ }
+}
+
+void yagl_sharegroup_mutex_unlock_if_shared(struct yagl_sharegroup *sg)
+{
+ if (yagl_sharegroup_is_shared(sg)) {
+ pthread_mutex_unlock(&sg->mutex);
+ }
+}
diff --git a/EGL/yagl_transport.c b/EGL/yagl_transport.c
index fbd4bf2..598583b 100644
--- a/EGL/yagl_transport.c
+++ b/EGL/yagl_transport.c
@@ -35,6 +35,7 @@
#include "yagl_malloc.h"
#include "yagl_log.h"
#include "yagl_egl_fence.h"
+#include "yagl_utils.h"
#include <stdio.h>
#include <stdlib.h>
diff --git a/GLES_common/yagl_gles_calls.c b/GLES_common/yagl_gles_calls.c
index a87f4c5..41e3368 100644
--- a/GLES_common/yagl_gles_calls.c
+++ b/GLES_common/yagl_gles_calls.c
@@ -420,6 +420,8 @@ YAGL_API void glBindBuffer(GLenum target, GLuint buffer)
YAGL_GET_CTX();
+ yagl_sharegroup_mutex_lock_if_shared(ctx->base.sg);
+
if (buffer != 0) {
buffer_obj = (struct yagl_gles_buffer*)yagl_sharegroup_acquire_object(ctx->base.sg,
YAGL_NS_BUFFER, buffer);
@@ -441,6 +443,8 @@ YAGL_API void glBindBuffer(GLenum target, GLuint buffer)
out:
yagl_gles_buffer_release(buffer_obj);
+ yagl_sharegroup_mutex_unlock_if_shared(ctx->base.sg);
+
YAGL_LOG_FUNC_EXIT(NULL);
}
@@ -452,6 +456,8 @@ void glBindFramebuffer(GLenum target, GLuint framebuffer)
YAGL_GET_CTX();
+ yagl_sharegroup_mutex_lock_if_shared(ctx->base.sg);
+
if (framebuffer != 0) {
framebuffer_obj = (struct yagl_gles_framebuffer*)yagl_namespace_acquire(&ctx->framebuffers,
framebuffer);
@@ -473,6 +479,8 @@ void glBindFramebuffer(GLenum target, GLuint framebuffer)
out:
yagl_gles_framebuffer_release(framebuffer_obj);
+ yagl_sharegroup_mutex_unlock_if_shared(ctx->base.sg);
+
YAGL_LOG_FUNC_EXIT(NULL);
}
@@ -484,6 +492,8 @@ void glBindRenderbuffer(GLenum target, GLuint renderbuffer)
YAGL_GET_CTX();
+ yagl_sharegroup_mutex_lock_if_shared(ctx->base.sg);
+
if (renderbuffer != 0) {
renderbuffer_obj = (struct yagl_gles_renderbuffer*)yagl_sharegroup_acquire_object(ctx->base.sg,
YAGL_NS_RENDERBUFFER, renderbuffer);
@@ -505,6 +515,8 @@ void glBindRenderbuffer(GLenum target, GLuint renderbuffer)
out:
yagl_gles_renderbuffer_release(renderbuffer_obj);
+ yagl_sharegroup_mutex_unlock_if_shared(ctx->base.sg);
+
YAGL_LOG_FUNC_EXIT(NULL);
}
@@ -517,6 +529,8 @@ YAGL_API void glBindTexture(GLenum target, GLuint texture)
YAGL_GET_CTX();
+ yagl_sharegroup_mutex_lock_if_shared(ctx->base.sg);
+
if (!yagl_gles_context_validate_texture_target(ctx, target, &texture_target)) {
YAGL_SET_ERR(GL_INVALID_ENUM);
goto out;
@@ -527,14 +541,8 @@ YAGL_API void glBindTexture(GLenum target, GLuint texture)
YAGL_NS_TEXTURE, texture);
if (!texture_obj) {
- texture_obj = yagl_gles_texture_create();
-
- if (!texture_obj) {
- goto out;
- }
-
- texture_obj = (struct yagl_gles_texture*)yagl_sharegroup_add_named(ctx->base.sg,
- YAGL_NS_TEXTURE, texture, &texture_obj->base);
+ YAGL_SET_ERR(GL_INVALID_OPERATION);
+ goto out;
}
}
@@ -543,6 +551,8 @@ YAGL_API void glBindTexture(GLenum target, GLuint texture)
out:
yagl_gles_texture_release(texture_obj);
+ yagl_sharegroup_mutex_unlock_if_shared(ctx->base.sg);
+
YAGL_LOG_FUNC_EXIT(NULL);
}
@@ -1029,6 +1039,8 @@ YAGL_API void glDeleteBuffers(GLsizei n, const GLuint *buffers)
YAGL_GET_CTX();
+ yagl_sharegroup_mutex_lock_if_shared(ctx->base.sg);
+
if (n < 0) {
YAGL_SET_ERR(GL_INVALID_VALUE);
goto out;
@@ -1045,6 +1057,8 @@ YAGL_API void glDeleteBuffers(GLsizei n, const GLuint *buffers)
}
out:
+ yagl_sharegroup_mutex_unlock_if_shared(ctx->base.sg);
+
YAGL_LOG_FUNC_EXIT(NULL);
}
@@ -1056,6 +1070,8 @@ void glDeleteFramebuffers(GLsizei n, const GLuint *framebuffers)
YAGL_GET_CTX();
+ yagl_sharegroup_mutex_lock_if_shared(ctx->base.sg);
+
if (n < 0) {
YAGL_SET_ERR(GL_INVALID_VALUE);
goto out;
@@ -1071,6 +1087,8 @@ void glDeleteFramebuffers(GLsizei n, const GLuint *framebuffers)
}
out:
+ yagl_sharegroup_mutex_unlock_if_shared(ctx->base.sg);
+
YAGL_LOG_FUNC_EXIT(NULL);
}
@@ -1082,6 +1100,8 @@ void glDeleteRenderbuffers(GLsizei n, const GLuint *renderbuffers)
YAGL_GET_CTX();
+ yagl_sharegroup_mutex_lock_if_shared(ctx->base.sg);
+
if (n < 0) {
YAGL_SET_ERR(GL_INVALID_VALUE);
goto out;
@@ -1098,6 +1118,8 @@ void glDeleteRenderbuffers(GLsizei n, const GLuint *renderbuffers)
}
out:
+ yagl_sharegroup_mutex_unlock_if_shared(ctx->base.sg);
+
YAGL_LOG_FUNC_EXIT(NULL);
}
@@ -1109,6 +1131,8 @@ YAGL_API void glDeleteTextures(GLsizei n, const GLuint *textures)
YAGL_GET_CTX();
+ yagl_sharegroup_mutex_lock_if_shared(ctx->base.sg);
+
if (n < 0) {
YAGL_SET_ERR(GL_INVALID_VALUE);
goto out;
@@ -1126,6 +1150,8 @@ YAGL_API void glDeleteTextures(GLsizei n, const GLuint *textures)
}
out:
+ yagl_sharegroup_mutex_unlock_if_shared(ctx->base.sg);
+
YAGL_LOG_FUNC_EXIT(NULL);
}
@@ -1411,6 +1437,8 @@ YAGL_API void glGenBuffers(GLsizei n, GLuint *buffer_names)
YAGL_GET_CTX();
+ yagl_sharegroup_mutex_lock_if_shared(ctx->base.sg);
+
if (n < 0) {
YAGL_SET_ERR(GL_INVALID_VALUE);
goto out;
@@ -1442,6 +1470,8 @@ out:
}
yagl_free(buffers);
+ yagl_sharegroup_mutex_unlock_if_shared(ctx->base.sg);
+
YAGL_LOG_FUNC_EXIT(NULL);
}
@@ -1469,6 +1499,8 @@ void glGenFramebuffers(GLsizei n, GLuint *framebuffer_names)
YAGL_GET_CTX();
+ yagl_sharegroup_mutex_lock_if_shared(ctx->base.sg);
+
if (n < 0) {
YAGL_SET_ERR(GL_INVALID_VALUE);
goto out;
@@ -1499,6 +1531,8 @@ out:
}
yagl_free(framebuffers);
+ yagl_sharegroup_mutex_unlock_if_shared(ctx->base.sg);
+
YAGL_LOG_FUNC_EXIT(NULL);
}
@@ -1511,6 +1545,8 @@ void glGenRenderbuffers(GLsizei n, GLuint *renderbuffer_names)
YAGL_GET_CTX();
+ yagl_sharegroup_mutex_lock_if_shared(ctx->base.sg);
+
if (n < 0) {
YAGL_SET_ERR(GL_INVALID_VALUE);
goto out;
@@ -1542,6 +1578,8 @@ out:
}
yagl_free(renderbuffers);
+ yagl_sharegroup_mutex_unlock_if_shared(ctx->base.sg);
+
YAGL_LOG_FUNC_EXIT(NULL);
}
@@ -1554,6 +1592,8 @@ YAGL_API void glGenTextures(GLsizei n, GLuint *texture_names)
YAGL_GET_CTX();
+ yagl_sharegroup_mutex_lock_if_shared(ctx->base.sg);
+
if (n < 0) {
YAGL_SET_ERR(GL_INVALID_VALUE);
goto out;
@@ -1585,6 +1625,8 @@ out:
}
yagl_free(textures);
+ yagl_sharegroup_mutex_unlock_if_shared(ctx->base.sg);
+
YAGL_LOG_FUNC_EXIT(NULL);
}
@@ -2432,6 +2474,8 @@ YAGL_API void glEGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image)
YAGL_GET_CTX();
+ yagl_sharegroup_mutex_lock_if_shared(ctx->base.sg);
+
switch (target) {
case GL_TEXTURE_2D:
texture_target = yagl_gles_texture_target_2d;
@@ -2464,6 +2508,8 @@ YAGL_API void glEGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image)
out:
yagl_gles_image_release(image_obj);
+ yagl_sharegroup_mutex_unlock_if_shared(ctx->base.sg);
+
YAGL_LOG_FUNC_EXIT(NULL);
}
diff --git a/GLES_common/yagl_gles_texture.c b/GLES_common/yagl_gles_texture.c
index e0f5e3d..e9a0580 100644
--- a/GLES_common/yagl_gles_texture.c
+++ b/GLES_common/yagl_gles_texture.c
@@ -266,8 +266,6 @@ void yagl_gles_texture_set_image(struct yagl_gles_texture *texture,
if (texture->image) {
yagl_gles_image_release(texture->image);
- } else {
- yagl_host_glDeleteObjects(&texture->global_name, 1);
}
texture->global_name = image->tex_global_name;
@@ -314,8 +312,6 @@ void yagl_gles_texture_bind_tex_image(struct yagl_gles_texture *texture,
if (texture->image) {
yagl_gles_image_release(texture->image);
- } else {
- yagl_host_glDeleteObjects(&texture->global_name, 1);
}
texture->global_name = image->tex_global_name;
diff --git a/GLES_common/yagl_host_gles_calls.c b/GLES_common/yagl_host_gles_calls.c
index a810c02..df7a628 100644
--- a/GLES_common/yagl_host_gles_calls.c
+++ b/GLES_common/yagl_host_gles_calls.c
@@ -406,6 +406,7 @@ void yagl_host_glGenBuffers(const GLuint *buffers, int32_t buffers_count)
yagl_transport_begin(t, yagl_api_id_gles, 27, 2 * 8, 0 * 8 + yagl_transport_array_size(buffers, buffers_count, sizeof(GLuint)));
yagl_transport_put_out_array(t, buffers, buffers_count, sizeof(GLuint));
yagl_transport_end(t);
+ yagl_transport_flush(t, NULL);
}
/*
@@ -519,6 +520,7 @@ void yagl_host_glGenTextures(const GLuint *textures, int32_t textures_count)
yagl_transport_begin(t, yagl_api_id_gles, 35, 2 * 8, 0 * 8 + yagl_transport_array_size(textures, textures_count, sizeof(GLuint)));
yagl_transport_put_out_array(t, textures, textures_count, sizeof(GLuint));
yagl_transport_end(t);
+ yagl_transport_flush(t, NULL);
}
/*
@@ -976,6 +978,7 @@ void yagl_host_glGenFramebuffers(const GLuint *framebuffers, int32_t framebuffer
yagl_transport_begin(t, yagl_api_id_gles, 63, 2 * 8, 0 * 8 + yagl_transport_array_size(framebuffers, framebuffers_count, sizeof(GLuint)));
yagl_transport_put_out_array(t, framebuffers, framebuffers_count, sizeof(GLuint));
yagl_transport_end(t);
+ yagl_transport_flush(t, NULL);
}
/*
@@ -1167,6 +1170,7 @@ void yagl_host_glGenRenderbuffers(const GLuint *renderbuffers, int32_t renderbuf
yagl_transport_begin(t, yagl_api_id_gles, 76, 2 * 8, 0 * 8 + yagl_transport_array_size(renderbuffers, renderbuffers_count, sizeof(GLuint)));
yagl_transport_put_out_array(t, renderbuffers, renderbuffers_count, sizeof(GLuint));
yagl_transport_end(t);
+ yagl_transport_flush(t, NULL);
}
/*
@@ -1237,6 +1241,7 @@ void yagl_host_glCreateProgram(GLuint program)
yagl_transport_begin(t, yagl_api_id_gles, 81, 1 * 8, 1 * 8);
yagl_transport_put_out_GLuint(t, program);
yagl_transport_end(t);
+ yagl_transport_flush(t, NULL);
}
/*
@@ -1250,6 +1255,7 @@ void yagl_host_glCreateShader(GLuint shader, GLenum type)
yagl_transport_put_out_GLuint(t, shader);
yagl_transport_put_out_GLenum(t, type);
yagl_transport_end(t);
+ yagl_transport_flush(t, NULL);
}
/*
@@ -2644,6 +2650,7 @@ void yagl_host_glDeleteObjects(const GLuint *objects, int32_t objects_count)
yagl_transport_begin(t, yagl_api_id_gles, 180, 2 * 8, 0 * 8 + yagl_transport_array_size(objects, objects_count, sizeof(GLuint)));
yagl_transport_put_out_array(t, objects, objects_count, sizeof(GLuint));
yagl_transport_end(t);
+ yagl_transport_flush(t, NULL);
}
/*
diff --git a/GLESv2/yagl_gles2_calls.c b/GLESv2/yagl_gles2_calls.c
index 45befd7..72d27ba 100644
--- a/GLESv2/yagl_gles2_calls.c
+++ b/GLESv2/yagl_gles2_calls.c
@@ -198,6 +198,8 @@ YAGL_API void glAttachShader(GLuint program, GLuint shader)
YAGL_GET_CTX();
+ yagl_sharegroup_mutex_lock_if_shared(ctx->sg);
+
program_obj = (struct yagl_gles2_program*)yagl_sharegroup_acquire_object(ctx->sg,
YAGL_NS_SHADER_PROGRAM, program);
@@ -233,6 +235,8 @@ out:
yagl_gles2_shader_release(shader_obj);
yagl_gles2_program_release(program_obj);
+ yagl_sharegroup_mutex_unlock_if_shared(ctx->sg);
+
YAGL_LOG_FUNC_EXIT(NULL);
}
@@ -339,6 +343,8 @@ YAGL_API GLuint glCreateProgram(void)
YAGL_GET_CTX_RET(0);
+ yagl_sharegroup_mutex_lock_if_shared(ctx->sg);
+
program = yagl_gles2_program_create(ctx->gen_locations);
if (!program) {
@@ -351,6 +357,8 @@ YAGL_API GLuint glCreateProgram(void)
out:
yagl_gles2_program_release(program);
+ yagl_sharegroup_mutex_unlock_if_shared(ctx->sg);
+
YAGL_LOG_FUNC_EXIT_SPLIT(GLuint, res);
return res;
@@ -365,6 +373,8 @@ YAGL_API GLuint glCreateShader(GLenum type)
YAGL_GET_CTX_RET(0);
+ yagl_sharegroup_mutex_lock_if_shared(ctx->sg);
+
if (yagl_gles2_is_shader_type_valid(type)) {
shader = yagl_gles2_shader_create(type);
@@ -381,6 +391,8 @@ YAGL_API GLuint glCreateShader(GLenum type)
out:
yagl_gles2_shader_release(shader);
+ yagl_sharegroup_mutex_unlock_if_shared(ctx->sg);
+
YAGL_LOG_FUNC_EXIT_SPLIT(GLuint, res);
return res;
@@ -394,6 +406,8 @@ YAGL_API void glDeleteProgram(GLuint program)
YAGL_GET_CTX();
+ yagl_sharegroup_mutex_lock_if_shared(ctx->sg);
+
if (program == 0) {
goto out;
}
@@ -419,6 +433,8 @@ YAGL_API void glDeleteProgram(GLuint program)
out:
yagl_gles2_program_release(program_obj);
+ yagl_sharegroup_mutex_unlock_if_shared(ctx->sg);
+
YAGL_LOG_FUNC_EXIT(NULL);
}
@@ -430,6 +446,8 @@ YAGL_API void glDeleteShader(GLuint shader)
YAGL_GET_CTX();
+ yagl_sharegroup_mutex_lock_if_shared(ctx->sg);
+
if (shader == 0) {
goto out;
}
@@ -453,6 +471,8 @@ YAGL_API void glDeleteShader(GLuint shader)
out:
yagl_gles2_shader_release(shader_obj);
+ yagl_sharegroup_mutex_unlock_if_shared(ctx->sg);
+
YAGL_LOG_FUNC_EXIT(NULL);
}
@@ -1347,6 +1367,8 @@ YAGL_API void glShaderSource(GLuint shader, GLsizei count, const GLchar * const
YAGL_GET_CTX();
+ yagl_sharegroup_mutex_lock_if_shared(ctx->sg);
+
if (count < 0) {
YAGL_SET_ERR(GL_INVALID_VALUE);
goto out;
@@ -1439,6 +1461,8 @@ YAGL_API void glShaderSource(GLuint shader, GLsizei count, const GLchar * const
out:
yagl_gles2_shader_release(shader_obj);
+ yagl_sharegroup_mutex_unlock_if_shared(ctx->sg);
+
YAGL_LOG_FUNC_EXIT(NULL);
}
diff --git a/include/yagl_client_context.h b/include/yagl_client_context.h
index 91057a5..25d73cf 100644
--- a/include/yagl_client_context.h
+++ b/include/yagl_client_context.h
@@ -36,6 +36,7 @@
#include "yagl_export.h"
#include "yagl_types.h"
+#include <pthread.h>
struct yagl_sharegroup;
struct yagl_client_image;
diff --git a/include/yagl_sharegroup.h b/include/yagl_sharegroup.h
index 868beb7..7dabd06 100644
--- a/include/yagl_sharegroup.h
+++ b/include/yagl_sharegroup.h
@@ -46,6 +46,7 @@
struct yagl_sharegroup
{
struct yagl_ref ref;
+ pthread_mutex_t mutex;
struct yagl_namespace namespaces[YAGL_NUM_NAMESPACES];
@@ -111,4 +112,14 @@ YAGL_API struct yagl_object *yagl_sharegroup_acquire_object(struct yagl_sharegro
int ns,
yagl_object_name local_name);
+/*
+ * Lock sharegroup's mutex if context is shared.
+ */
+YAGL_API void yagl_sharegroup_mutex_lock_if_shared(struct yagl_sharegroup *sg);
+
+/*
+ * Unlock sharegroup's mutex if context is shared.
+ */
+YAGL_API void yagl_sharegroup_mutex_unlock_if_shared(struct yagl_sharegroup *sg);
+
#endif
diff --git a/include/yagl_transport.h b/include/yagl_transport.h
index 62d4d6d..d69d228 100644
--- a/include/yagl_transport.h
+++ b/include/yagl_transport.h
@@ -39,6 +39,7 @@
#include <string.h>
#include <assert.h>
#include <limits.h>
+#include <pthread.h>
#define YAGL_TRANSPORT_MAX_IN_ARGS 8
#define YAGL_TRANSPORT_MAX_IN_ARRAYS 8