Commit 5914cf51 authored by sletz's avatar sletz
Browse files

Better memory allocation error checking in ringbuffer.c, weak import improvements.

git-svn-id: http://subversion.jackaudio.org/jack/jack2/trunk/jackmp@3777 0c269be4-1314-0410-8aa9-9f06e86f4224
parent fcda3c22
......@@ -25,6 +25,10 @@ Paul Davis
Jackdmp changes log
---------------------------
2009-11-13 Stephane Letz <letz@grame.fr>
* Better memory allocation error checking in ringbuffer.c, weak import improvements.
2009-11-12 Stephane Letz <letz@grame.fr>
* Better memory allocation error checking on client (library) side.
......
......@@ -21,7 +21,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Completed from Julien Pommier (PianoTeq : http://www.pianoteq.com/) code.
*/
#include "jack.h"
#include <jack/jack.h>
#include <math.h>
#include <dlfcn.h>
#include <stdlib.h>
......@@ -81,7 +81,7 @@ DECL_FUNCTION(const char *, jack_get_version_string, (), ());
DECL_FUNCTION(jack_client_t *, jack_client_open, (const char *client_name, jack_options_t options, jack_status_t *status, ...),
(client_name, options, status));
DECL_FUNCTION(int, jack_client_close, (jack_client_t *client), (client));
DECL_FUNCTION(int, jack_client_new, (const char *client_name), (client_name));
DECL_FUNCTION(jack_client_t *, jack_client_new, (const char *client_name), (client_name));
DECL_FUNCTION(int, jack_client_name_size, (), ());
DECL_FUNCTION(char*, jack_get_client_name, (jack_client_t *client), (client));
DECL_FUNCTION(int, jack_internal_client_new, (const char *client_name,
......@@ -89,8 +89,8 @@ DECL_FUNCTION(int, jack_internal_client_new, (const char *client_name,
const char *load_init), (client_name, load_name, load_init));
DECL_VOID_FUNCTION(jack_internal_client_close, (const char *client_name), (client_name));
DECL_FUNCTION(int, jack_is_realtime, (jack_client_t *client), (client));
DECL_VOID_FUNCTION(jack_on_shutdown, (jack_client_t *client, JackShutdownCallback shutdown_callback, void *arg), (client, function, arg));
DECL_VOID_FUNCTION(jack_on_info_shutdown, (jack_client_t* ext_client, JackInfoShutdownCallback callback, void* arg, (client, function, arg))
DECL_VOID_FUNCTION(jack_on_shutdown, (jack_client_t *client, JackShutdownCallback shutdown_callback, void *arg), (client, shutdown_callback, arg));
DECL_VOID_FUNCTION(jack_on_info_shutdown, (jack_client_t* client, JackInfoShutdownCallback shutdown_callback, void* arg), (client, shutdown_callback, arg));
DECL_FUNCTION(int, jack_set_process_callback, (jack_client_t *client,
JackProcessCallback process_callback,
void *arg), (client, process_callback, arg));
......@@ -98,7 +98,7 @@ DECL_FUNCTION(jack_nframes_t, jack_thread_wait, (jack_client_t *client, int stat
//
DECL_FUNCTION(jack_nframes_t, jack_cycle_wait, (jack_client_t *client), (client));
DECL_VOID_FUNCTION(jack_cycle_signal, (jack_client_t *client, , int status), (client, status));
DECL_VOID_FUNCTION(jack_cycle_signal, (jack_client_t *client, int status), (client, status));
DECL_FUNCTION(int, jack_set_process_thread, (jack_client_t *client,
JackThreadCallback fun,
void *arg), (client, fun, arg));
......@@ -153,11 +153,11 @@ DECL_FUNCTION(const char**, jack_port_get_connections, (const jack_port_t *port)
DECL_FUNCTION(const char**, jack_port_get_all_connections, (const jack_port_t *port), (port));
DECL_FUNCTION(int, jack_port_tie, (jack_port_t *src, jack_port_t *dst), (src, dst));
DECL_FUNCTION(int, jack_port_untie, (jack_port_t *port), (port));
DECL_FUNCTION(jack_nframes_t, jack_port_get_latency, (jack_port_t *port));
DECL_FUNCTION(jack_nframes_t, jack_port_get_latency, (jack_client_t *), (jack_port_t *port));
DECL_FUNCTION(jack_nframes_t, jack_port_get_total_latency ,(jack_client_t *), (jack_port_t *port));
DECL_VOID_FUNCTION(jack_port_set_latency, (jack_port_t *), (jack_nframes_t));
DECL_FUNCTION(int, jack_recompute_total_latency, (jack_client_t*), (jack_port_t* port));
DECL_FUNCTION(int, jack_recompute_total_latencies, (jack_client_t*));
DECL_FUNCTION(int, jack_recompute_total_latencies, (jack_client_t*),(client));
DECL_FUNCTION(int, jack_port_set_name, (jack_port_t *port), (const char *port_name));
DECL_FUNCTION(int, jack_port_set_alias, (jack_port_t *port), (const char *alias));
......@@ -239,5 +239,5 @@ DECL_FUNCTION(int jack_midi_event_get(jack_midi_event_t* event, void* port_buffe
DECL_VOID_FUNCTION(jack_midi_clear_buffer, (void* port_buffer));
DECL_FUNCTION(size_t, jack_midi_max_event_size, (void* port_buffer));
DECL_FUNCTION(jack_midi_data_t*, jack_midi_event_reserve, (void* port_buffer), (jack_nframes_t time), (size_t data_size));
DECL_FUNCTIO(int jack_midi_event_write, (void* port_buffer), (jack_nframes_t time), (const jack_midi_data_t* data), (size_t data_size));
DECL_FUNCTION(int jack_midi_event_write, (void* port_buffer), (jack_nframes_t time), (const jack_midi_data_t* data), (size_t data_size));
DECL_FUNCTION(jack_nframes_t, jack_midi_get_lost_event_count, (void* port_buffer));
......@@ -34,6 +34,25 @@ extern "C"
* Note: More documentation can be found in jack/types.h.
*/
/*************************************************************
* NOTE: JACK_WEAK_EXPORT ***MUST*** be used on every function
* added to the JACK API after the 0.116.2 release.
*************************************************************/
#ifndef JACK_WEAK_EXPORT
#ifdef __GNUC__
/* JACK_WEAK_EXPORT needs to be a macro which
expands into a compiler directive. If non-null, the directive
must tell the compiler to arrange for weak linkage of
the symbol it used with. For this to work full may
require linker arguments in the client as well.
*/
#define JACK_WEAK_EXPORT __attribute__((weak))
#else
/* Add other things here for non-gcc platforms */
#endif
#endif
/**
* @defgroup ClientFunctions Creating & manipulating clients
* @{
......@@ -301,7 +320,7 @@ int jack_set_thread_init_callback (jack_client_t *client,
* jack_on_info_shutdown() will.
*/
void jack_on_shutdown (jack_client_t *client,
JackShutdownCallback shutdown_callback, void *arg);
JackShutdownCallback shutdown_callback, void *arg) JACK_WEAK_EXPORT;
/**
* @param client pointer to JACK client structure.
......
<
......@@ -64,252 +64,244 @@ size_t jack_ringbuffer_write_space(const jack_ringbuffer_t *rb);
/* Create a new ringbuffer to hold at least `sz' bytes of data. The
actual buffer size is rounded up to the next power of two. */
EXPORT jack_ringbuffer_t *
jack_ringbuffer_t *
jack_ringbuffer_create (size_t sz)
{
int power_of_two;
jack_ringbuffer_t *rb;
rb = (jack_ringbuffer_t*)malloc (sizeof (jack_ringbuffer_t));
for (power_of_two = 1; 1 << power_of_two < sz; power_of_two++);
rb->size = 1 << power_of_two;
rb->size_mask = rb->size;
rb->size_mask -= 1;
rb->write_ptr = 0;
rb->read_ptr = 0;
rb->buf = (char*)malloc (rb->size);
memset(rb->buf, 0, rb->size);
rb->mlocked = 0;
return rb;
int power_of_two;
jack_ringbuffer_t *rb;
if ((rb = malloc (sizeof (jack_ringbuffer_t))) == NULL) {
return NULL;
}
for (power_of_two = 1; 1 << power_of_two < sz; power_of_two++);
rb->size = 1 << power_of_two;
rb->size_mask = rb->size;
rb->size_mask -= 1;
rb->write_ptr = 0;
rb->read_ptr = 0;
if ((rb->buf = malloc (rb->size)) == NULL) {
free (rb);
return NULL;
}
rb->mlocked = 0;
return rb;
}
/* Free all data associated with the ringbuffer `rb'. */
EXPORT void
void
jack_ringbuffer_free (jack_ringbuffer_t * rb)
{
#ifdef USE_MLOCK
if (rb->mlocked) {
munlock (rb->buf, rb->size);
}
if (rb->mlocked) {
munlock (rb->buf, rb->size);
}
#endif /* USE_MLOCK */
free (rb->buf);
free (rb);
free (rb->buf);
free (rb);
}
/* Lock the data block of `rb' using the system call 'mlock'. */
EXPORT int
int
jack_ringbuffer_mlock (jack_ringbuffer_t * rb)
{
#ifdef USE_MLOCK
if (mlock (rb->buf, rb->size)) {
return -1;
}
if (mlock (rb->buf, rb->size)) {
return -1;
}
#endif /* USE_MLOCK */
rb->mlocked = 1;
return 0;
rb->mlocked = 1;
return 0;
}
/* Reset the read and write pointers to zero. This is not thread
safe. */
EXPORT void
void
jack_ringbuffer_reset (jack_ringbuffer_t * rb)
{
rb->read_ptr = 0;
rb->write_ptr = 0;
}
/* Reset the read and write pointers to zero. This is not thread
safe. */
EXPORT void
jack_ringbuffer_reset_size (jack_ringbuffer_t * rb, size_t sz)
{
rb->size = sz;
rb->size_mask = rb->size;
rb->size_mask -= 1;
rb->read_ptr = 0;
rb->write_ptr = 0;
rb->read_ptr = 0;
rb->write_ptr = 0;
}
/* Return the number of bytes available for reading. This is the
number of bytes in front of the read pointer and behind the write
pointer. */
EXPORT size_t
size_t
jack_ringbuffer_read_space (const jack_ringbuffer_t * rb)
{
size_t w, r;
w = rb->write_ptr;
r = rb->read_ptr;
if (w > r) {
return w - r;
} else {
return (w - r + rb->size) & rb->size_mask;
}
size_t w, r;
w = rb->write_ptr;
r = rb->read_ptr;
if (w > r) {
return w - r;
} else {
return (w - r + rb->size) & rb->size_mask;
}
}
/* Return the number of bytes available for writing. This is the
number of bytes in front of the write pointer and behind the read
pointer. */
EXPORT size_t
size_t
jack_ringbuffer_write_space (const jack_ringbuffer_t * rb)
{
size_t w, r;
w = rb->write_ptr;
r = rb->read_ptr;
if (w > r) {
return ((r - w + rb->size) & rb->size_mask) - 1;
} else if (w < r) {
return (r - w) - 1;
} else {
return rb->size - 1;
}
size_t w, r;
w = rb->write_ptr;
r = rb->read_ptr;
if (w > r) {
return ((r - w + rb->size) & rb->size_mask) - 1;
} else if (w < r) {
return (r - w) - 1;
} else {
return rb->size - 1;
}
}
/* The copying data reader. Copy at most `cnt' bytes from `rb' to
`dest'. Returns the actual number of bytes copied. */
EXPORT size_t
size_t
jack_ringbuffer_read (jack_ringbuffer_t * rb, char *dest, size_t cnt)
{
size_t free_cnt;
size_t cnt2;
size_t to_read;
size_t n1, n2;
size_t free_cnt;
size_t cnt2;
size_t to_read;
size_t n1, n2;
if ((free_cnt = jack_ringbuffer_read_space (rb)) == 0) {
return 0;
}
if ((free_cnt = jack_ringbuffer_read_space (rb)) == 0) {
return 0;
}
to_read = cnt > free_cnt ? free_cnt : cnt;
to_read = cnt > free_cnt ? free_cnt : cnt;
cnt2 = rb->read_ptr + to_read;
cnt2 = rb->read_ptr + to_read;
if (cnt2 > rb->size) {
n1 = rb->size - rb->read_ptr;
n2 = cnt2 & rb->size_mask;
} else {
n1 = to_read;
n2 = 0;
}
if (cnt2 > rb->size) {
n1 = rb->size - rb->read_ptr;
n2 = cnt2 & rb->size_mask;
} else {
n1 = to_read;
n2 = 0;
}
memcpy (dest, &(rb->buf[rb->read_ptr]), n1);
rb->read_ptr = (rb->read_ptr + n1) & rb->size_mask;
memcpy (dest, &(rb->buf[rb->read_ptr]), n1);
rb->read_ptr = (rb->read_ptr + n1) & rb->size_mask;
if (n2) {
memcpy (dest + n1, &(rb->buf[rb->read_ptr]), n2);
rb->read_ptr = (rb->read_ptr + n2) & rb->size_mask;
}
if (n2) {
memcpy (dest + n1, &(rb->buf[rb->read_ptr]), n2);
rb->read_ptr = (rb->read_ptr + n2) & rb->size_mask;
}
return to_read;
return to_read;
}
/* The copying data reader w/o read pointer advance. Copy at most
`cnt' bytes from `rb' to `dest'. Returns the actual number of bytes
copied. */
/* The copying data reader w/o read pointer advance. Copy at most
`cnt' bytes from `rb' to `dest'. Returns the actual number of bytes
copied. */
EXPORT size_t
size_t
jack_ringbuffer_peek (jack_ringbuffer_t * rb, char *dest, size_t cnt)
{
size_t free_cnt;
size_t cnt2;
size_t to_read;
size_t n1, n2;
size_t tmp_read_ptr;
size_t free_cnt;
size_t cnt2;
size_t to_read;
size_t n1, n2;
size_t tmp_read_ptr;
tmp_read_ptr = rb->read_ptr;
tmp_read_ptr = rb->read_ptr;
if ((free_cnt = jack_ringbuffer_read_space (rb)) == 0) {
return 0;
}
if ((free_cnt = jack_ringbuffer_read_space (rb)) == 0) {
return 0;
}
to_read = cnt > free_cnt ? free_cnt : cnt;
to_read = cnt > free_cnt ? free_cnt : cnt;
cnt2 = tmp_read_ptr + to_read;
cnt2 = tmp_read_ptr + to_read;
if (cnt2 > rb->size) {
n1 = rb->size - tmp_read_ptr;
n2 = cnt2 & rb->size_mask;
} else {
n1 = to_read;
n2 = 0;
}
if (cnt2 > rb->size) {
n1 = rb->size - tmp_read_ptr;
n2 = cnt2 & rb->size_mask;
} else {
n1 = to_read;
n2 = 0;
}
memcpy (dest, &(rb->buf[tmp_read_ptr]), n1);
tmp_read_ptr = (tmp_read_ptr + n1) & rb->size_mask;
memcpy (dest, &(rb->buf[tmp_read_ptr]), n1);
tmp_read_ptr = (tmp_read_ptr + n1) & rb->size_mask;
if (n2) {
memcpy (dest + n1, &(rb->buf[tmp_read_ptr]), n2);
}
if (n2) {
memcpy (dest + n1, &(rb->buf[tmp_read_ptr]), n2);
}
return to_read;
return to_read;
}
/* The copying data writer. Copy at most `cnt' bytes to `rb' from
`src'. Returns the actual number of bytes copied. */
EXPORT size_t
size_t
jack_ringbuffer_write (jack_ringbuffer_t * rb, const char *src, size_t cnt)
{
size_t free_cnt;
size_t cnt2;
size_t to_write;
size_t n1, n2;
size_t free_cnt;
size_t cnt2;
size_t to_write;
size_t n1, n2;
if ((free_cnt = jack_ringbuffer_write_space (rb)) == 0) {
return 0;
}
if ((free_cnt = jack_ringbuffer_write_space (rb)) == 0) {
return 0;
}
to_write = cnt > free_cnt ? free_cnt : cnt;
to_write = cnt > free_cnt ? free_cnt : cnt;
cnt2 = rb->write_ptr + to_write;
cnt2 = rb->write_ptr + to_write;
if (cnt2 > rb->size) {
n1 = rb->size - rb->write_ptr;
n2 = cnt2 & rb->size_mask;
} else {
n1 = to_write;
n2 = 0;
}
if (cnt2 > rb->size) {
n1 = rb->size - rb->write_ptr;
n2 = cnt2 & rb->size_mask;
} else {
n1 = to_write;
n2 = 0;
}
memcpy (&(rb->buf[rb->write_ptr]), src, n1);
rb->write_ptr = (rb->write_ptr + n1) & rb->size_mask;
memcpy (&(rb->buf[rb->write_ptr]), src, n1);
rb->write_ptr = (rb->write_ptr + n1) & rb->size_mask;
if (n2) {
memcpy (&(rb->buf[rb->write_ptr]), src + n1, n2);
rb->write_ptr = (rb->write_ptr + n2) & rb->size_mask;
}
if (n2) {
memcpy (&(rb->buf[rb->write_ptr]), src + n1, n2);
rb->write_ptr = (rb->write_ptr + n2) & rb->size_mask;
}
return to_write;
return to_write;
}
/* Advance the read pointer `cnt' places. */
EXPORT void
void
jack_ringbuffer_read_advance (jack_ringbuffer_t * rb, size_t cnt)
{
size_t tmp = (rb->read_ptr + cnt) & rb->size_mask;
rb->read_ptr = tmp;
size_t tmp = (rb->read_ptr + cnt) & rb->size_mask;
rb->read_ptr = tmp;
}
/* Advance the write pointer `cnt' places. */
EXPORT void
void
jack_ringbuffer_write_advance (jack_ringbuffer_t * rb, size_t cnt)
{
size_t tmp = (rb->write_ptr + cnt) & rb->size_mask;
rb->write_ptr = tmp;
size_t tmp = (rb->write_ptr + cnt) & rb->size_mask;
rb->write_ptr = tmp;
}
/* The non-copying data reader. `vec' is an array of two places. Set
......@@ -317,43 +309,43 @@ jack_ringbuffer_write_advance (jack_ringbuffer_t * rb, size_t cnt)
the readable data is in one segment the second segment has zero
length. */
EXPORT void
void
jack_ringbuffer_get_read_vector (const jack_ringbuffer_t * rb,
jack_ringbuffer_data_t * vec)
{
size_t free_cnt;
size_t cnt2;
size_t w, r;
size_t free_cnt;
size_t cnt2;
size_t w, r;
w = rb->write_ptr;
r = rb->read_ptr;
w = rb->write_ptr;
r = rb->read_ptr;
if (w > r) {
free_cnt = w - r;
} else {
free_cnt = (w - r + rb->size) & rb->size_mask;
}
if (w > r) {
free_cnt = w - r;
} else {
free_cnt = (w - r + rb->size) & rb->size_mask;
}
cnt2 = r + free_cnt;
cnt2 = r + free_cnt;
if (cnt2 > rb->size) {
if (cnt2 > rb->size) {
/* Two part vector: the rest of the buffer after the current write
ptr, plus some from the start of the buffer. */
/* Two part vector: the rest of the buffer after the current write
ptr, plus some from the start of the buffer. */
vec[0].buf = &(rb->buf[r]);
vec[0].len = rb->size - r;
vec[1].buf = rb->buf;
vec[1].len = cnt2 & rb->size_mask;
vec[0].buf = &(rb->buf[r]);
vec[0].len = rb->size - r;
vec[1].buf = rb->buf;
vec[1].len = cnt2 & rb->size_mask;
} else {
} else {
/* Single part vector: just the rest of the buffer */
/* Single part vector: just the rest of the buffer */
vec[0].buf = &(rb->buf[r]);
vec[0].len = free_cnt;
vec[1].len = 0;
}
vec[0].buf = &(rb->buf[r]);
vec[0].len = free_cnt;
vec[1].len = 0;
}
}
/* The non-copying data writer. `vec' is an array of two places. Set
......@@ -361,39 +353,39 @@ jack_ringbuffer_get_read_vector (const jack_ringbuffer_t * rb,
the writeable data is in one segment the second segment has zero
length. */
EXPORT void
void
jack_ringbuffer_get_write_vector (const jack_ringbuffer_t * rb,
jack_ringbuffer_data_t * vec)
{
size_t free_cnt;
size_t cnt2;
size_t w, r;
w = rb->write_ptr;
r = rb->read_ptr;
if (w > r) {
free_cnt = ((r - w + rb->size) & rb->size_mask) - 1;
} else if (w < r) {
free_cnt = (r - w) - 1;
} else {
free_cnt = rb->size - 1;
}
cnt2 = w + free_cnt;
if (cnt2 > rb->size) {
/* Two part vector: the rest of the buffer after the current write
ptr, plus some from the start of the buffer. */
vec[0].buf = &(rb->buf[w]);
vec[0].len = rb->size - w;
vec[1].buf = rb->buf;
vec[1].len = cnt2 & rb->size_mask;
} else {
vec[0].buf = &(rb->buf[w]);
vec[0].len = free_cnt;
vec[1].len = 0;
}