blob: 995986a9d03ba2263f147e7ce7a81a00845c9610 [file] [log] [blame]
/*
* sync.c
*
* DSP-BIOS Bridge driver support functions for TI OMAP processors.
*
* Synchronization services.
*
* Copyright (C) 2005-2006 Texas Instruments, Inc.
*
* This package is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
/* ----------------------------------- Host OS */
#include <dspbridge/host_os.h>
/* ----------------------------------- This */
#include <dspbridge/sync.h>
#include <dspbridge/ntfy.h>
DEFINE_SPINLOCK(sync_lock);
/**
* sync_set_event() - set or signal and specified event
* @event: Event to be set..
*
* set the @event, if there is an thread waiting for the event
* it will be waken up, this function only wakes one thread.
*/
void sync_set_event(struct sync_object *event)
{
spin_lock_bh(&sync_lock);
complete(&event->comp);
if (event->multi_comp)
complete(event->multi_comp);
spin_unlock_bh(&sync_lock);
}
/**
* sync_wait_on_multiple_events() - waits for multiple events to be set.
* @events: Array of events to wait for them.
* @count: number of elements of the array.
* @timeout timeout on waiting for the evetns.
* @pu_index index of the event set.
*
* This functios will wait until any of the array element is set or until
* timeout. In case of success the function will return 0 and
* @pu_index will store the index of the array element set or in case
* of timeout the function will return -ETIME or in case of
* interrupting by a signal it will return -EPERM.
*/
int sync_wait_on_multiple_events(struct sync_object **events,
unsigned count, unsigned timeout,
unsigned *index)
{
unsigned i;
int status = -EPERM;
struct completion m_comp;
init_completion(&m_comp);
if (SYNC_INFINITE == timeout)
timeout = MAX_SCHEDULE_TIMEOUT;
spin_lock_bh(&sync_lock);
for (i = 0; i < count; i++) {
if (completion_done(&events[i]->comp)) {
INIT_COMPLETION(events[i]->comp);
*index = i;
spin_unlock_bh(&sync_lock);
status = 0;
goto func_end;
}
}
for (i = 0; i < count; i++)
events[i]->multi_comp = &m_comp;
spin_unlock_bh(&sync_lock);
if (!wait_for_completion_interruptible_timeout(&m_comp,
msecs_to_jiffies(timeout)))
status = -ETIME;
spin_lock_bh(&sync_lock);
for (i = 0; i < count; i++) {
if (completion_done(&events[i]->comp)) {
INIT_COMPLETION(events[i]->comp);
*index = i;
status = 0;
}
events[i]->multi_comp = NULL;
}
spin_unlock_bh(&sync_lock);
func_end:
return status;
}
/**
* dsp_notifier_event() - callback function to nofity events
* @this: pointer to itself struct notifier_block
* @event: event to be notified.
* @data: Currently not used.
*
*/
int dsp_notifier_event(struct notifier_block *this, unsigned long event,
void *data)
{
struct ntfy_event *ne = container_of(this, struct ntfy_event,
noti_block);
if (ne->event & event)
sync_set_event(&ne->sync_obj);
return NOTIFY_OK;
}