summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar waker <wakeroid@gmail.com>2009-08-28 20:30:20 +0200
committerGravatar waker <wakeroid@gmail.com>2009-08-28 20:30:20 +0200
commitf263abb8b777b61bcce7eee88716a137d0f880c3 (patch)
tree4e1b2c27affb8e9f3c27726b04b0fe9909cc919a
parent81d1b50a3bd28099b784e5b2a14295e715a48d01 (diff)
lastfm multithreading WIP
-rw-r--r--deadbeef.h5
-rw-r--r--main.c4
-rw-r--r--plugins.c7
-rw-r--r--plugins/lastfm/Makefile.am2
-rw-r--r--plugins/lastfm/lastfm.c339
-rw-r--r--threading.h7
-rw-r--r--threading_pthread.c52
7 files changed, 277 insertions, 139 deletions
diff --git a/deadbeef.h b/deadbeef.h
index 2dfefda9..cd3583be 100644
--- a/deadbeef.h
+++ b/deadbeef.h
@@ -128,6 +128,11 @@ typedef struct {
void (*mutex_free) (uintptr_t mtx);
int (*mutex_lock) (uintptr_t mtx);
int (*mutex_unlock) (uintptr_t mtx);
+ uintptr_t (*cond_create) (void);
+ void (*cond_free) (uintptr_t cond);
+ int (*cond_wait) (uintptr_t cond, uintptr_t mutex);
+ int (*cond_signal) (uintptr_t cond);
+ int (*cond_broadcast) (uintptr_t cond);
// playlist access
const char *(*pl_find_meta) (DB_playItem_t *song, const char *meta);
// volume control
diff --git a/main.c b/main.c
index 28f3ff73..885eaa9c 100644
--- a/main.c
+++ b/main.c
@@ -20,6 +20,7 @@
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
+#include <time.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/types.h>
@@ -494,6 +495,7 @@ on_trayicon_popup_menu (GtkWidget *widget,
int
main (int argc, char *argv[]) {
+ srand (time (NULL));
prctl (PR_SET_NAME, "deadbeef-main", 0, 0, 0, 0);
char *homedir = getenv ("HOME");
if (!homedir) {
@@ -653,7 +655,7 @@ main (int argc, char *argv[]) {
p_free ();
streamer_free ();
codec_free_locking ();
-
+ plug_unload_all ();
session_save (sessfile);
pl_save (defpl);
pl_free ();
diff --git a/plugins.c b/plugins.c
index 7157cc8d..d5b88903 100644
--- a/plugins.c
+++ b/plugins.c
@@ -36,11 +36,18 @@ DB_functions_t deadbeef_api = {
.playback_get_pos = plug_playback_get_pos,
.playback_set_pos = plug_playback_set_pos,
.quit = plug_quit,
+ // threading
.thread_start = thread_start,
.mutex_create = mutex_create,
.mutex_free = mutex_free,
.mutex_lock = mutex_lock,
.mutex_unlock = mutex_unlock,
+ .cond_create = cond_create,
+ .cond_free = cond_free,
+ .cond_wait = cond_wait,
+ .cond_signal = cond_signal,
+ .cond_broadcast = cond_broadcast,
+ // metadata
.pl_find_meta = (const char *(*) (DB_playItem_t *song, const char *meta))pl_find_meta,
// volume control
.volume_set_db = volume_set_db,
diff --git a/plugins/lastfm/Makefile.am b/plugins/lastfm/Makefile.am
index 7e26b863..24fb0f4b 100644
--- a/plugins/lastfm/Makefile.am
+++ b/plugins/lastfm/Makefile.am
@@ -4,4 +4,4 @@ lastfm_la_SOURCES = lastfm.c
lastfm_la_LDFLAGS = -module
lastfm_la_LIBADD = $(LDADD) $(LASTFM_DEPS_LIBS)
-AM_CFLAGS = $(LASTFM_DEPS_CFLAGS)
+AM_CFLAGS = $(LASTFM_DEPS_CFLAGS) -std=c99
diff --git a/plugins/lastfm/lastfm.c b/plugins/lastfm/lastfm.c
index 2d805ff6..15c9508e 100644
--- a/plugins/lastfm/lastfm.c
+++ b/plugins/lastfm/lastfm.c
@@ -36,12 +36,16 @@ static DB_functions_t *deadbeef;
#define LFM_API_KEY "6b33c8ae4d598a9aff8fe63e334e6e86"
#define LFM_API_SECRET "a9f5e17e358377d96e96477d870b2b18"
-char lfm_user[100];
-char lfm_pass[100];
+static char lfm_user[100];
+static char lfm_pass[100];
-char lfm_sess[33];
-char lfm_nowplaying_url[256];
-char lfm_submission_url[256];
+static char lfm_sess[33];
+static char lfm_nowplaying_url[256];
+static char lfm_submission_url[256];
+
+static uintptr_t lfm_mutex;
+static uintptr_t lfm_cond;
+static int lfm_stopthread;
DB_plugin_t *
lastfm_load (DB_functions_t *api) {
@@ -54,6 +58,10 @@ static char lfm_reply[MAX_REPLY];
static char lfm_reply_sz;
static char lfm_err[CURL_ERROR_SIZE];
+#define LFM_SUBMISSION_QUEUE_SIZE 5
+static char lfm_nowplaying[2048]; // packet for nowplaying, or ""
+static char lfm_subm_queue[LFM_SUBMISSION_QUEUE_SIZE][2048];
+
static size_t
lastfm_curl_res (void *ptr, size_t size, size_t nmemb, void *stream)
{
@@ -64,10 +72,10 @@ lastfm_curl_res (void *ptr, size_t size, size_t nmemb, void *stream)
}
memcpy (lfm_reply + lfm_reply_sz, ptr, len);
lfm_reply_sz += len;
- char s[size*nmemb+1];
- memcpy (s, ptr, size*nmemb);
- s[size*nmemb] = 0;
- fprintf (stderr, "got from net: %s\n", s);
+// char s[size*nmemb+1];
+// memcpy (s, ptr, size*nmemb);
+// s[size*nmemb] = 0;
+// fprintf (stderr, "got from net: %s\n", s);
return len;
}
@@ -107,95 +115,6 @@ curl_req_cleanup (void) {
lfm_reply_sz = 0;
}
-
-// {{{ lastfm v2 get session
-#if 0
-int
-auth_v2 (void) {
- if (lfm_sess[0]) {
- return 0;
- }
- char msg[4096];
- char sigstr[4096];
- uint8_t sig[16];
- snprintf (sigstr, sizeof (sigstr), "api_key%smethodauth.getToken%s", LASTFM_API_KEY, LASTFM_API_SECRET);
- deadbeef->md5 (sig, sigstr, strlen (sigstr));
- deadbeef->md5_to_str (sigstr, sig);
- snprintf (msg, sizeof (msg), "%s/?api_key=%s&method=auth.getToken&api_sig=%s", SCROBBLER_URL, LASTFM_API_KEY, sigstr);
- // get token
- char lfm_token[33] = "";
- int status = curl_req_send (msg, NULL);
- if (!status) {
- // parse output
- if (strstr (lfm_reply, "<lfm status=\"ok\">")) {
- char *token = strstr (lfm_reply, "<token>");
- if (token) {
- token += 7;
- char *end = strstr (token, "</token>");
- if (end) {
- *end = 0;
- snprintf (msg, sizeof (msg), "http://www.last.fm/api/auth/?api_key=%s&token=%s", LASTFM_API_KEY, token);
- printf ("Dear user. Please visit this URL and authenticate deadbeef. Thanks.\n");
-
- printf ("%s\n", msg);
- strncpy (lfm_token, token, 32);
- lfm_token[32] = 0;
- }
- }
- }
- }
- curl_req_cleanup ();
- if (!lfm_token[0]) {
- // total fail, give up
- return -1;
- }
- // get session
- snprintf (sigstr, sizeof (sigstr), "api_key%smethodauth.getSessiontoken%s%s", LASTFM_API_KEY, lfm_token, LASTFM_API_SECRET);
- deadbeef->md5 (sig, sigstr, strlen (sigstr));
- deadbeef->md5_to_str (sigstr, sig);
- snprintf (msg, sizeof (msg), "method=auth.getSession&token=%s&api_key=%s&api_sig=%s", lfm_token, LASTFM_API_KEY, sigstr);
- for (;;) {
- status = curl_req_send (SCROBBLER_URL, msg);
- if (!status) {
- char *sess = strstr (lfm_reply, "<key>");
- if (sess) {
- sess += 5;
- char *end = strstr (sess, "</key>");
- if (end) {
- *end = 0;
- char config[1024];
- snprintf (config, sizeof (config), "%s/.config/deadbeef/lastfmv2", getenv ("HOME"));
- fprintf (stderr, "got session key %s\n", sess);
- FILE *fp = fopen (config, "w+b");
- if (!fp) {
- fprintf (stderr, "lastfm: failed to write config file %s\n", config);
- curl_req_cleanup ();
- return -1;
- }
- if (fwrite (sess, 1, 32, fp) != 32) {
- fclose (fp);
- fprintf (stderr, "lastfm: failed to write config file %s\n", config);
- curl_req_cleanup ();
- return -1;
- }
- fclose (fp);
- strcpy (lfm_sess, sess);
- }
- }
-// printf ("reply: %s\n", lfm_reply);
- }
- curl_req_cleanup ();
- if (lfm_sess[0]) {
- break;
- }
- sleep (5);
- }
- return 0;
-}
-#endif
-// }}}
-
-
int
auth (void) {
if (lfm_sess[0]) {
@@ -206,7 +125,6 @@ auth (void) {
uint8_t sig[16];
char passmd5[33];
char token[100];
- printf (">> %s:%s <<\n", lfm_user, lfm_pass);
deadbeef->md5 (sig, lfm_pass, strlen (lfm_pass));
deadbeef->md5_to_str (passmd5, sig);
snprintf (token, sizeof (token), "%s%d", passmd5, timestamp);
@@ -221,7 +139,6 @@ auth (void) {
// handshake
int status = curl_req_send (req, NULL);
if (!status) {
- printf ("%s\n", lfm_reply);
// check status and extract session id, nowplaying url, submission url
if (strncmp (lfm_reply, "OK", 2)) {
uint8_t *p = lfm_reply;
@@ -334,7 +251,7 @@ lfm_fetch_song_info (DB_playItem_t *song, const char **a, const char **t, const
static int
lastfm_songstarted (DB_event_song_t *ev, uintptr_t data) {
- printf ("song started, info:\n");
+ fprintf (stderr, "song started, info:\n");
const char *a; // artist
const char *t; // title
const char *b; // album
@@ -342,36 +259,24 @@ lastfm_songstarted (DB_event_song_t *ev, uintptr_t data) {
const char *n; // tracknum
const char *m; // muzicbrainz id
if (lfm_fetch_song_info (ev->song, &a, &t, &b, &l, &n, &m) == 0) {
- printf ("playtime: %f\nartist: %s\ntitle: %s\nalbum: %s\nduration: %f\ntracknum: %s\n---\n", ev->song->playtime, a, t, b, l, n);
+ fprintf (stderr, "playtime: %f\nartist: %s\ntitle: %s\nalbum: %s\nduration: %f\ntracknum: %s\n---\n", ev->song->playtime, a, t, b, l, n);
}
else {
- printf ("file %s doesn't have enough tags to submit to last.fm\n", ev->song->fname);
+ fprintf (stderr, "file %s doesn't have enough tags to submit to last.fm\n", ev->song->fname);
return 0;
}
- // submit to nowplaying
- if (auth () < 0) {
- return;
- }
-
- char req[4096];
- snprintf (req, sizeof (req), "s=%s&a=%s&t=%s&b=%s&l=%d&n=%s&m=%s", lfm_sess, a, t, b, (int)l, n, m);
- fprintf (stderr, "sending nowplaying to lfm:\n%s\n", req);
- int status = curl_req_send (lfm_nowplaying_url, req);
- if (!status) {
- if (strncmp (lfm_reply, "OK", 2)) {
- fprintf (stderr, "nowplaying failed, response:\n%s\n", lfm_reply);
- lfm_sess[0] = 0;
- }
- }
- curl_req_cleanup ();
+ deadbeef->mutex_lock (lfm_mutex);
+ snprintf (lfm_nowplaying, sizeof (lfm_nowplaying), "a=%s&t=%s&b=%s&l=%d&n=%s&m=%s", a, t, b, (int)l, n, m);
+ deadbeef->mutex_unlock (lfm_mutex);
+ deadbeef->cond_signal (lfm_cond);
return 0;
}
static int
lastfm_songfinished (DB_event_song_t *ev, uintptr_t data) {
- printf ("song finished, info:\n");
+ fprintf (stderr, "song finished, info:\n");
const char *a; // artist
const char *t; // title
const char *b; // album
@@ -379,16 +284,14 @@ lastfm_songfinished (DB_event_song_t *ev, uintptr_t data) {
const char *n; // tracknum
const char *m; // muzicbrainz id
if (lfm_fetch_song_info (ev->song, &a, &t, &b, &l, &n, &m) == 0) {
- printf ("playtime: %f\nartist: %s\ntitle: %s\nalbum: %s\nduration: %f\ntracknum: %s\n---\n", ev->song->playtime, a, t, b, l, n);
+ fprintf (stderr, "playtime: %f\nartist: %s\ntitle: %s\nalbum: %s\nduration: %f\ntracknum: %s\n---\n", ev->song->playtime, a, t, b, l, n);
}
else {
- printf ("file %s doesn't have enough tags to submit to last.fm\n", ev->song->fname);
+ fprintf (stderr, "file %s doesn't have enough tags to submit to last.fm\n", ev->song->fname);
return 0;
}
// check submission rules
-
-#if 0
// must be played for >=240sec of half the total time
if (ev->song->playtime < 240 && ev->song->playtime < ev->song->duration/2) {
return 0;
@@ -399,27 +302,196 @@ lastfm_songfinished (DB_event_song_t *ev, uintptr_t data) {
return 0;
}
+ deadbeef->mutex_lock (lfm_mutex);
+ // find free place in queue
+ for (int i = 0; i < LFM_SUBMISSION_QUEUE_SIZE; i++) {
+ if (!lfm_subm_queue[i][0]) {
+ snprintf (lfm_subm_queue[i], sizeof (lfm_subm_queue[i]), "a[0]=%s&t[0]=%s&i[0]=%d&o[0]=P&r[0]=&b[0]=%s&l[0]=%d&n[0]=%s&m[0]=%s", a, t, ev->song->started_timestamp, b, (int)l, n, m);
+ break;
+ }
+ }
+ deadbeef->mutex_unlock (lfm_mutex);
+ deadbeef->cond_signal (lfm_cond);
+
+ return 0;
+}
+
+static void
+lfm_send_nowplaying (void) {
if (auth () < 0) {
+ lfm_nowplaying[0] = 0;
return;
}
-#endif
-
- char req[4096];
- snprintf (req, sizeof (req), "s=%s&a[0]=%s&t[0]=%s&i[0]=%d&o[0]=P&r[0]=&b[0]=%s&l[0]=%d&n[0]=%s&m[0]=%s", lfm_sess, a, t, ev->song->started_timestamp, b, (int)l, n, m);
- fprintf (stderr, "sending submission to lfm:\n%s\n", req);
- int status = curl_req_send (lfm_submission_url, req);
+ fprintf (stderr, "auth successful! setting nowplaying\n");
+ char s[100];
+ snprintf (s, sizeof (s), "&s=%s", lfm_sess);
+ strcat (lfm_nowplaying, s);
+ int status = curl_req_send (lfm_nowplaying_url, lfm_nowplaying);
if (!status) {
if (strncmp (lfm_reply, "OK", 2)) {
- fprintf (stderr, "submission failed, response:\n%s\n", lfm_reply);
+ fprintf (stderr, "nowplaying failed, response:\n%s\n", lfm_reply);
lfm_sess[0] = 0;
}
}
curl_req_cleanup ();
+ lfm_nowplaying[0] = 0;
+}
+
+static void
+lfm_send_submissions (void) {
+ if (auth () < 0) {
+ return;
+ }
+ for (;;) {
+ int i;
+ deadbeef->mutex_lock (lfm_mutex);
+ for (i = 0; i < LFM_SUBMISSION_QUEUE_SIZE; i++) {
+ if (lfm_subm_queue[i][0]) {
+ break;
+ }
+ }
+ deadbeef->mutex_unlock (lfm_mutex);
+ if (i == LFM_SUBMISSION_QUEUE_SIZE) {
+ break;
+ }
+ int status = curl_req_send (lfm_submission_url, lfm_subm_queue[i]);
+ if (!status) {
+ if (strncmp (lfm_reply, "OK", 2)) {
+ fprintf (stderr, "submission failed, response:\n%s\n", lfm_reply);
+ lfm_sess[0] = 0;
+ }
+ else {
+ deadbeef->mutex_lock (lfm_mutex);
+ lfm_subm_queue[i][0] = 0;
+ deadbeef->mutex_unlock (lfm_mutex);
+ }
+ }
+ curl_req_cleanup ();
+ if (!lfm_sess[0]) {
+ break;
+ }
+ }
+}
+
+void
+lfm_thread (uintptr_t ctx) {
+ //fprintf (stderr, "lfm_thread started\n");
+ for (;;) {
+ deadbeef->cond_wait (lfm_cond, lfm_mutex);
+ fprintf (stderr, "cond signalled!\n");
+ if (lfm_stopthread) {
+ deadbeef->mutex_unlock (lfm_mutex);
+ fprintf (stderr, "lfm_thread end\n");
+ deadbeef->cond_free (lfm_cond);
+ deadbeef->mutex_free (lfm_mutex);
+ return;
+ }
+ deadbeef->mutex_unlock (lfm_mutex);
+
+ // try to send nowplaying
+ if (lfm_nowplaying[0]) {
+ lfm_send_nowplaying ();
+ }
+
+ lfm_send_submissions ();
+ }
+}
+
+// {{{ lastfm v2 get session
+#if 0
+int
+auth_v2 (void) {
+ if (lfm_sess[0]) {
+ return 0;
+ }
+ char msg[4096];
+ char sigstr[4096];
+ uint8_t sig[16];
+ snprintf (sigstr, sizeof (sigstr), "api_key%smethodauth.getToken%s", LASTFM_API_KEY, LASTFM_API_SECRET);
+ deadbeef->md5 (sig, sigstr, strlen (sigstr));
+ deadbeef->md5_to_str (sigstr, sig);
+ snprintf (msg, sizeof (msg), "%s/?api_key=%s&method=auth.getToken&api_sig=%s", SCROBBLER_URL, LASTFM_API_KEY, sigstr);
+ // get token
+ char lfm_token[33] = "";
+ int status = curl_req_send (msg, NULL);
+ if (!status) {
+ // parse output
+ if (strstr (lfm_reply, "<lfm status=\"ok\">")) {
+ char *token = strstr (lfm_reply, "<token>");
+ if (token) {
+ token += 7;
+ char *end = strstr (token, "</token>");
+ if (end) {
+ *end = 0;
+ snprintf (msg, sizeof (msg), "http://www.last.fm/api/auth/?api_key=%s&token=%s", LASTFM_API_KEY, token);
+ fprintf (stderr, "Dear user. Please visit this URL and authenticate deadbeef. Thanks.\n");
+
+ fprintf (stderr, "%s\n", msg);
+ strncpy (lfm_token, token, 32);
+ lfm_token[32] = 0;
+ }
+ }
+ }
+ }
+ curl_req_cleanup ();
+ if (!lfm_token[0]) {
+ // total fail, give up
+ return -1;
+ }
+ // get session
+ snprintf (sigstr, sizeof (sigstr), "api_key%smethodauth.getSessiontoken%s%s", LASTFM_API_KEY, lfm_token, LASTFM_API_SECRET);
+ deadbeef->md5 (sig, sigstr, strlen (sigstr));
+ deadbeef->md5_to_str (sigstr, sig);
+ snprintf (msg, sizeof (msg), "method=auth.getSession&token=%s&api_key=%s&api_sig=%s", lfm_token, LASTFM_API_KEY, sigstr);
+ for (;;) {
+ status = curl_req_send (SCROBBLER_URL, msg);
+ if (!status) {
+ char *sess = strstr (lfm_reply, "<key>");
+ if (sess) {
+ sess += 5;
+ char *end = strstr (sess, "</key>");
+ if (end) {
+ *end = 0;
+ char config[1024];
+ snprintf (config, sizeof (config), "%s/.config/deadbeef/lastfmv2", getenv ("HOME"));
+ fprintf (stderr, "got session key %s\n", sess);
+ FILE *fp = fopen (config, "w+b");
+ if (!fp) {
+ fprintf (stderr, "lastfm: failed to write config file %s\n", config);
+ curl_req_cleanup ();
+ return -1;
+ }
+ if (fwrite (sess, 1, 32, fp) != 32) {
+ fclose (fp);
+ fprintf (stderr, "lastfm: failed to write config file %s\n", config);
+ curl_req_cleanup ();
+ return -1;
+ }
+ fclose (fp);
+ strcpy (lfm_sess, sess);
+ }
+ }
+// fprintf (stderr, "reply: %s\n", lfm_reply);
+ }
+ curl_req_cleanup ();
+ if (lfm_sess[0]) {
+ break;
+ }
+ sleep (5);
+ }
return 0;
}
+#endif
+// }}}
+
+
static int
lastfm_start (void) {
+ lfm_stopthread = 0;
+ lfm_mutex = deadbeef->mutex_create ();
+ lfm_cond = deadbeef->cond_create ();
+ deadbeef->thread_start (lfm_thread, 0);
// subscribe to frameupdate event
deadbeef->ev_subscribe (DB_PLUGIN (&plugin), DB_EV_SONGSTARTED, DB_CALLBACK (lastfm_songstarted), 0);
deadbeef->ev_subscribe (DB_PLUGIN (&plugin), DB_EV_SONGFINISHED, DB_CALLBACK (lastfm_songfinished), 0);
@@ -477,15 +549,18 @@ lastfm_start (void) {
}
p++;
*p = 0;
- auth ();
return 0;
}
static int
lastfm_stop (void) {
+ //fprintf (stderr, "lastfm_stop\n");
deadbeef->ev_unsubscribe (DB_PLUGIN (&plugin), DB_EV_SONGSTARTED, DB_CALLBACK (lastfm_songstarted), 0);
deadbeef->ev_unsubscribe (DB_PLUGIN (&plugin), DB_EV_SONGFINISHED, DB_CALLBACK (lastfm_songfinished), 0);
+ lfm_stopthread = 1;
+ deadbeef->cond_signal (lfm_cond);
+ fprintf (stderr, "signalled to stop thread\n");
return 0;
}
diff --git a/threading.h b/threading.h
index 824432c1..cb71b933 100644
--- a/threading.h
+++ b/threading.h
@@ -21,10 +21,17 @@
#include <stdint.h>
void thread_start (void (*fn)(uintptr_t ctx), uintptr_t ctx);
+
uintptr_t mutex_create (void);
void mutex_free (uintptr_t mtx);
int mutex_lock (uintptr_t mtx);
int mutex_unlock (uintptr_t mtx);
+uintptr_t cond_create (void);
+void cond_free (uintptr_t cond);
+int cond_wait (uintptr_t cond, uintptr_t mutex);
+int cond_signal (uintptr_t cond);
+int cond_broadcast (uintptr_t cond);
+
#endif
diff --git a/threading_pthread.c b/threading_pthread.c
index ae8bf258..7bb3d50b 100644
--- a/threading_pthread.c
+++ b/threading_pthread.c
@@ -20,7 +20,8 @@
#include <stdlib.h>
#include "threading.h"
-void thread_start (void (*fn)(uintptr_t ctx), uintptr_t ctx) {
+void
+thread_start (void (*fn)(uintptr_t ctx), uintptr_t ctx) {
pthread_t tid;
pthread_attr_t attr;
int s = pthread_attr_init (&attr);
@@ -39,30 +40,71 @@ void thread_start (void (*fn)(uintptr_t ctx), uintptr_t ctx) {
return;
}
}
-uintptr_t mutex_create (void) {
+uintptr_t
+mutex_create (void) {
pthread_mutex_t *mtx = malloc (sizeof (pthread_mutex_t));
if (pthread_mutex_init (mtx, NULL)) {
printf ("pthread_mutex_init failed!\n");
}
return (uintptr_t)mtx;
}
-void mutex_free (uintptr_t _mtx) {
+
+void
+mutex_free (uintptr_t _mtx) {
pthread_mutex_t *mtx = (pthread_mutex_t *)_mtx;
mutex_lock (_mtx);
mutex_unlock (_mtx);
pthread_mutex_destroy (mtx);
free (mtx);
}
-int mutex_lock (uintptr_t _mtx) {
+
+int
+mutex_lock (uintptr_t _mtx) {
pthread_mutex_t *mtx = (pthread_mutex_t *)_mtx;
if (pthread_mutex_lock (mtx)) {
printf ("pthread_mutex_lock failed\n");
}
}
-int mutex_unlock (uintptr_t _mtx) {
+
+int
+mutex_unlock (uintptr_t _mtx) {
pthread_mutex_t *mtx = (pthread_mutex_t *)_mtx;
if (pthread_mutex_unlock (mtx)) {
printf ("pthread_mutex_unlock failed\n");
};
}
+uintptr_t
+cond_create (void) {
+ pthread_cond_t *cond = malloc (sizeof (pthread_cond_t));
+ pthread_cond_init (cond, NULL);
+ return (uintptr_t)cond;
+}
+
+void
+cond_free (uintptr_t c) {
+ if (c) {
+ pthread_cond_t *cond = (pthread_cond_t *)c;
+ pthread_cond_destroy (cond);
+ free (cond);
+ }
+}
+
+int
+cond_wait (uintptr_t c, uintptr_t m) {
+ pthread_cond_t *cond = (pthread_cond_t *)c;
+ pthread_mutex_t *mutex = (pthread_mutex_t *)m;
+ return pthread_cond_wait (cond, mutex);
+}
+
+int
+cond_signal (uintptr_t c) {
+ pthread_cond_t *cond = (pthread_cond_t *)c;
+ return pthread_cond_signal (cond);
+}
+
+int
+cond_broadcast (uintptr_t c) {
+ pthread_cond_t *cond = (pthread_cond_t *)c;
+ return pthread_cond_broadcast (cond);
+}