Phase in thread_wait when waiting for a thread to exit. Begin phasing out the spinlock object for general use; it will become a multicore-only object for core locking. Take care of plugins first.

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@15260 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Michael Sevakis 2007-10-22 05:57:38 +00:00
parent 344c41f644
commit 7e12bba0d2
6 changed files with 40 additions and 37 deletions

View file

@ -512,10 +512,12 @@ static const struct plugin_api rockbox_api = {
the API gets incompatible */ the API gets incompatible */
#if (CONFIG_CODEC == SWCODEC) #if (CONFIG_CODEC == SWCODEC)
spinlock_init, mutex_init,
spinlock_lock, mutex_lock,
spinlock_unlock, mutex_unlock,
#endif #endif
thread_wait,
}; };
int plugin_load(const char* plugin, void* parameter) int plugin_load(const char* plugin, void* parameter)

View file

@ -112,12 +112,12 @@
#define PLUGIN_MAGIC 0x526F634B /* RocK */ #define PLUGIN_MAGIC 0x526F634B /* RocK */
/* increase this every time the api struct changes */ /* increase this every time the api struct changes */
#define PLUGIN_API_VERSION 85 #define PLUGIN_API_VERSION 86
/* update this to latest version if a change to the api struct breaks /* update this to latest version if a change to the api struct breaks
backwards compatibility (and please take the opportunity to sort in any backwards compatibility (and please take the opportunity to sort in any
new function which are "waiting" at the end of the function table) */ new function which are "waiting" at the end of the function table) */
#define PLUGIN_MIN_API_VERSION 85 #define PLUGIN_MIN_API_VERSION 86
/* plugin return codes */ /* plugin return codes */
enum plugin_status { enum plugin_status {
@ -634,10 +634,12 @@ struct plugin_api {
the API gets incompatible */ the API gets incompatible */
#if (CONFIG_CODEC == SWCODEC) #if (CONFIG_CODEC == SWCODEC)
void (*spinlock_init)(struct spinlock *l IF_COP(, unsigned int flags)); void (*mutex_init)(struct mutex *m);
void (*spinlock_lock)(struct spinlock *l); void (*mutex_lock)(struct mutex *m);
void (*spinlock_unlock)(struct spinlock *l); void (*mutex_unlock)(struct mutex *m);
#endif #endif
void (*thread_wait)(struct thread_entry *thread);
}; };
/* plugin header */ /* plugin header */

View file

@ -204,7 +204,7 @@ struct
{ {
bool foreground; /* set as long as we're owning the UI */ bool foreground; /* set as long as we're owning the UI */
bool exiting; /* signal to the thread that we want to exit */ bool exiting; /* signal to the thread that we want to exit */
bool ended; /* response from the thread, that is has exited */ struct thread_entry *thread; /* worker thread id */
} gTread; } gTread;
static struct plugin_api* rb; /* here is the global API struct pointer */ static struct plugin_api* rb; /* here is the global API struct pointer */
@ -1112,8 +1112,6 @@ void thread(void)
} }
} while (!gTread.exiting); } while (!gTread.exiting);
gTread.ended = true; /* acknowledge the exit */
} }
/* callback to end the TSR plugin, called before a new one gets loaded */ /* callback to end the TSR plugin, called before a new one gets loaded */
@ -1122,8 +1120,7 @@ bool exit_tsr(bool reenter)
if (reenter) if (reenter)
return false; /* dont let it start again */ return false; /* dont let it start again */
gTread.exiting = true; /* tell the thread to end */ gTread.exiting = true; /* tell the thread to end */
while (!gTread.ended) /* wait until it did */ rb->thread_wait(gTread.thread); /* wait until it did */
rb->yield();
uart_init(BAUDRATE); /* return to standard baudrate */ uart_init(BAUDRATE); /* return to standard baudrate */
IPRE = (IPRE & ~0xF000); /* UART interrupt off */ IPRE = (IPRE & ~0xF000); /* UART interrupt off */
@ -1167,7 +1164,7 @@ int main(void* parameter)
rb->memset(&gTread, 0, sizeof(gTread)); rb->memset(&gTread, 0, sizeof(gTread));
gTread.foreground = true; gTread.foreground = true;
rb->create_thread(thread, stack, stacksize, 0, "CDC" gTread.thread = rb->create_thread(thread, stack, stacksize, 0, "CDC"
IF_PRIO(, PRIORITY_BACKGROUND) IF_PRIO(, PRIORITY_BACKGROUND)
IF_COP(, CPU)); IF_COP(, CPU));

View file

@ -133,8 +133,6 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
return main(); return main();
} }
bool thread_stopped = false;
/* Struct for battery information */ /* Struct for battery information */
struct batt_info struct batt_info
{ {
@ -147,6 +145,7 @@ struct batt_info
unsigned short flags; unsigned short flags;
} bat[BUF_SIZE/sizeof(struct batt_info)]; } bat[BUF_SIZE/sizeof(struct batt_info)];
struct thread_entry *thread_id;
struct event_queue thread_q; struct event_queue thread_q;
bool exit_tsr(bool reenter) bool exit_tsr(bool reenter)
@ -166,8 +165,7 @@ bool exit_tsr(bool reenter)
if (exit) if (exit)
{ {
rb->queue_post(&thread_q, EV_EXIT, 0); rb->queue_post(&thread_q, EV_EXIT, 0);
while (!thread_stopped) rb->thread_wait(thread_id);
rb->yield();
/* remove the thread's queue from the broadcast list */ /* remove the thread's queue from the broadcast list */
rb->queue_delete(&thread_q); rb->queue_delete(&thread_q);
return true; return true;
@ -350,7 +348,6 @@ void thread(void)
#else #else
"bench exit"); "bench exit");
#endif #endif
thread_stopped = true;
return; return;
} }
@ -373,7 +370,6 @@ void thread(void)
break; break;
} }
} while (1); } while (1);
} }
@ -499,10 +495,10 @@ int main(void)
} }
rb->queue_init(&thread_q, true); /* put the thread's queue in the bcast list */ rb->queue_init(&thread_q, true); /* put the thread's queue in the bcast list */
if(rb->create_thread(thread, thread_stack, if((thread_id = rb->create_thread(thread, thread_stack,
sizeof(thread_stack), 0, "Battery Benchmark" sizeof(thread_stack), 0, "Battery Benchmark"
IF_PRIO(, PRIORITY_BACKGROUND) IF_PRIO(, PRIORITY_BACKGROUND)
IF_COP(, CPU)) == NULL) IF_COP(, CPU))) == NULL)
{ {
rb->splash(HZ, "Cannot create thread!"); rb->splash(HZ, "Cannot create thread!");
return PLUGIN_ERROR; return PLUGIN_ERROR;

View file

@ -188,7 +188,7 @@ typedef struct
int have_msg; /* 1=event pending */ int have_msg; /* 1=event pending */
int replied; /* 1=replied to last event */ int replied; /* 1=replied to last event */
int reply; /* reply value */ int reply; /* reply value */
struct spinlock msg_lock; /* serialization for event senders */ struct mutex msg_lock; /* serialization for event senders */
uint8_t* curr_packet; /* Current stream packet beginning */ uint8_t* curr_packet; /* Current stream packet beginning */
uint8_t* curr_packet_end; /* Current stream packet end */ uint8_t* curr_packet_end; /* Current stream packet end */
@ -294,7 +294,7 @@ static intptr_t str_send_msg(Stream *str, int id, intptr_t data)
#endif #endif
/* Only one thread at a time, please */ /* Only one thread at a time, please */
rb->spinlock_lock(&str->msg_lock); rb->mutex_lock(&str->msg_lock);
str->ev.id = id; str->ev.id = id;
str->ev.data = data; str->ev.data = data;
@ -316,7 +316,7 @@ static intptr_t str_send_msg(Stream *str, int id, intptr_t data)
reply = str->reply; reply = str->reply;
rb->spinlock_unlock(&str->msg_lock); rb->mutex_unlock(&str->msg_lock);
return reply; return reply;
} }
@ -340,13 +340,13 @@ static size_t file_remaining IBSS_ATTR;
#if NUM_CORES > 1 #if NUM_CORES > 1
/* Some stream variables are shared between cores */ /* Some stream variables are shared between cores */
struct spinlock stream_lock IBSS_ATTR; struct mutex stream_lock IBSS_ATTR;
static inline void init_stream_lock(void) static inline void init_stream_lock(void)
{ rb->spinlock_init(&stream_lock, SPINLOCK_TASK_SWITCH); } { rb->mutex_init(&stream_lock); }
static inline void lock_stream(void) static inline void lock_stream(void)
{ rb->spinlock_lock(&stream_lock); } { rb->mutex_lock(&stream_lock); }
static inline void unlock_stream(void) static inline void unlock_stream(void)
{ rb->spinlock_unlock(&stream_lock); } { rb->mutex_unlock(&stream_lock); }
#else #else
/* No RMW issue here */ /* No RMW issue here */
static inline void init_stream_lock(void) static inline void init_stream_lock(void)
@ -1937,8 +1937,7 @@ void display_thumb(int in_file)
} }
else else
{ {
while (video_str.status != STREAM_TERMINATED) rb->thread_wait(video_str.thread);
rb->yield();
} }
if ( video_str.curr_packet_end == video_str.curr_packet) if ( video_str.curr_packet_end == video_str.curr_packet)
@ -2417,8 +2416,8 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
initialize_stream( &video_str, disk_buf_start, disk_buf_len, 0xe0 ); initialize_stream( &video_str, disk_buf_start, disk_buf_len, 0xe0 );
initialize_stream( &audio_str, disk_buf_start, disk_buf_len, 0xc0 ); initialize_stream( &audio_str, disk_buf_start, disk_buf_len, 0xc0 );
rb->spinlock_init(&audio_str.msg_lock IF_COP(, SPINLOCK_TASK_SWITCH)); rb->mutex_init(&audio_str.msg_lock);
rb->spinlock_init(&video_str.msg_lock IF_COP(, SPINLOCK_TASK_SWITCH)); rb->mutex_init(&video_str.msg_lock);
audio_str.status = STREAM_BUFFERING; audio_str.status = STREAM_BUFFERING;
video_str.status = STREAM_PLAYING; video_str.status = STREAM_PLAYING;
@ -2504,12 +2503,16 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
/* Stop the threads and wait for them to terminate */ /* Stop the threads and wait for them to terminate */
if (video_str.thread != NULL) if (video_str.thread != NULL)
{
str_send_msg(&video_str, STREAM_QUIT, 0); str_send_msg(&video_str, STREAM_QUIT, 0);
rb->thread_wait(video_str.thread);
}
if (audio_str.thread != NULL) if (audio_str.thread != NULL)
{
str_send_msg(&audio_str, STREAM_QUIT, 0); str_send_msg(&audio_str, STREAM_QUIT, 0);
rb->thread_wait(audio_str.thread);
rb->sleep(HZ/10); }
#if NUM_CORES > 1 #if NUM_CORES > 1
invalidate_icache(); invalidate_icache();

View file

@ -601,6 +601,9 @@ static enum plugin_status test_track(char* filename)
/* Save the current time before we spin up the disk to access the log */ /* Save the current time before we spin up the disk to access the log */
ticks = *rb->current_tick - starttick; ticks = *rb->current_tick - starttick;
/* Be sure it is done */
rb->thread_wait(codecthread_id);
log_text(str,true); log_text(str,true);
/* Close WAV file (if there was one) */ /* Close WAV file (if there was one) */