@ -161,87 +161,6 @@ MODULE_ALIAS("ip6t_RTPENGINE");
# define _w_unlock(l, f) write_unlock_irqrestore(l, f)
# define _w_unlock(l, f) write_unlock_irqrestore(l, f)
# endif
# endif
#if 0
# define _spinlock_t spinlock_t
# define _spin_lock_init(x) spin_lock_init(x)
# define _spin_lock(x) spin_lock(x)
# define _spin_unlock(x) spin_unlock(x)
# define _rwlock_t rwlock_t
# define _rwlock_init(x) rwlock_init(x)
# define _read_lock(x) read_lock(x)
# define _read_unlock(x) read_unlock(x)
# define _write_lock(x) write_lock(x)
# define _write_unlock(x) write_unlock(x)
# else
typedef struct {
spinlock_t l ;
int owner ;
int line ;
} _spinlock_t ;
static inline void _spin_lock_init ( _spinlock_t * s ) {
spin_lock_init ( & s - > l ) ;
s - > owner = 0 ;
}
static inline void __spin_lock ( _spinlock_t * s , int line ) {
unsigned int cnt = 0 ;
while ( true ) {
if ( spin_trylock ( & s - > l ) ) {
s - > owner = current - > pid ;
s - > line = line ;
return ;
}
cnt + + ;
if ( cnt = = 100000000 )
printk ( KERN_WARNING " %i stuck at %i, owned by %i at %i \n " , current - > pid , line , s - > owner , s - > line ) ;
}
}
static inline void _spin_unlock ( _spinlock_t * s ) {
s - > owner = 0 ;
spin_unlock ( & s - > l ) ;
}
typedef struct {
rwlock_t l ;
int owner ;
int line ;
} _rwlock_t ;
static inline void _rwlock_init ( _rwlock_t * s ) {
rwlock_init ( & s - > l ) ;
s - > owner = 0 ;
}
static inline void __read_lock ( _rwlock_t * s , int line ) {
unsigned int cnt = 0 ;
while ( true ) {
if ( read_trylock ( & s - > l ) )
return ;
cnt + + ;
if ( cnt = = 100000000 )
printk ( KERN_WARNING " %i stuck at %i, owned by %i at %i \n " , current - > pid , line , s - > owner , s - > line ) ;
}
}
static inline void _read_unlock ( _rwlock_t * s ) {
read_unlock ( & s - > l ) ;
}
static inline void __write_lock ( _rwlock_t * s , int line ) {
unsigned int cnt = 0 ;
while ( true ) {
if ( write_trylock ( & s - > l ) ) {
s - > owner = current - > pid ;
s - > line = line ;
return ;
}
cnt + + ;
if ( cnt = = 100000000 )
printk ( KERN_WARNING " %i stuck at %i, owned by %i at %i \n " , current - > pid , line , s - > owner , s - > line ) ;
}
}
static inline void _write_unlock ( _rwlock_t * s ) {
s - > owner = 0 ;
write_unlock ( & s - > l ) ;
}
# define _spin_lock(x) __spin_lock(x, __LINE__)
# define _read_lock(x) __read_lock(x, __LINE__)
# define _write_lock(x) __write_lock(x, __LINE__)
# endif
@ -525,7 +444,7 @@ struct rtpengine_table {
struct global_stats_counter * rtpe_stats ;
struct global_stats_counter * rtpe_stats ;
_ spinlock_t player_lock ;
spinlock_t player_lock ;
struct list_head play_streams ;
struct list_head play_streams ;
unsigned int num_play_streams ;
unsigned int num_play_streams ;
struct list_head packet_streams ;
struct list_head packet_streams ;
@ -609,7 +528,7 @@ struct play_stream_packet {
struct play_stream_packets {
struct play_stream_packets {
atomic_t refcnt ;
atomic_t refcnt ;
_ rwlock_t lock ;
rwlock_t lock ;
struct list_head packets ;
struct list_head packets ;
unsigned int len ;
unsigned int len ;
unsigned int table_id ;
unsigned int table_id ;
@ -618,7 +537,7 @@ struct play_stream_packets {
} ;
} ;
struct play_stream {
struct play_stream {
_ spinlock_t lock ;
spinlock_t lock ;
atomic_t refcnt ;
atomic_t refcnt ;
unsigned int idx ;
unsigned int idx ;
struct rtpengine_play_stream_info info ;
struct rtpengine_play_stream_info info ;
@ -640,7 +559,7 @@ struct timer_thread {
wait_queue_head_t queue ;
wait_queue_head_t queue ;
atomic_t shutdown ;
atomic_t shutdown ;
_ spinlock_t tree_lock ; // XXX use mutex?
spinlock_t tree_lock ; // XXX use mutex?
struct btree_head64 tree ; // timer entries // XXX use rbtree?
struct btree_head64 tree ; // timer entries // XXX use rbtree?
bool tree_added ;
bool tree_added ;
struct play_stream * scheduled ;
struct play_stream * scheduled ;
@ -667,7 +586,7 @@ static struct re_auto_array calls;
static struct re_auto_array streams ;
static struct re_auto_array streams ;
# ifdef KERNEL_PLAYER
# ifdef KERNEL_PLAYER
static _ rwlock_t media_player_lock ;
static rwlock_t media_player_lock ;
static struct play_stream_packets * * stream_packets ;
static struct play_stream_packets * * stream_packets ;
static unsigned int num_stream_packets ;
static unsigned int num_stream_packets ;
static atomic_t last_stream_packets_idx ;
static atomic_t last_stream_packets_idx ;
@ -929,7 +848,7 @@ static struct rtpengine_table *new_table(void) {
INIT_LIST_HEAD ( & t - > packet_streams ) ;
INIT_LIST_HEAD ( & t - > packet_streams ) ;
INIT_LIST_HEAD ( & t - > play_streams ) ;
INIT_LIST_HEAD ( & t - > play_streams ) ;
t - > id = - 1 ;
t - > id = - 1 ;
_ spin_lock_init( & t - > player_lock ) ;
spin_lock_init( & t - > player_lock ) ;
for ( i = 0 ; i < ARRAY_SIZE ( t - > calls_hash ) ; i + + ) {
for ( i = 0 ; i < ARRAY_SIZE ( t - > calls_hash ) ; i + + ) {
INIT_HLIST_HEAD ( & t - > calls_hash [ i ] ) ;
INIT_HLIST_HEAD ( & t - > calls_hash [ i ] ) ;
@ -1158,31 +1077,31 @@ static void clear_table_player(struct rtpengine_table *t) {
unsigned int idx ;
unsigned int idx ;
list_for_each_entry_safe ( stream , ts , & t - > play_streams , table_entry ) {
list_for_each_entry_safe ( stream , ts , & t - > play_streams , table_entry ) {
_ spin_lock( & stream - > lock ) ;
spin_lock( & stream - > lock ) ;
stream - > table_id = - 1 ;
stream - > table_id = - 1 ;
idx = stream - > idx ;
idx = stream - > idx ;
_ spin_unlock( & stream - > lock ) ;
spin_unlock( & stream - > lock ) ;
_ write_lock( & media_player_lock ) ;
write_lock( & media_player_lock ) ;
if ( play_streams [ idx ] = = stream ) {
if ( play_streams [ idx ] = = stream ) {
play_streams [ idx ] = NULL ;
play_streams [ idx ] = NULL ;
unref_play_stream ( stream ) ;
unref_play_stream ( stream ) ;
}
}
_ write_unlock( & media_player_lock ) ;
write_unlock( & media_player_lock ) ;
do_stop_stream ( stream ) ;
do_stop_stream ( stream ) ;
unref_play_stream ( stream ) ;
unref_play_stream ( stream ) ;
}
}
list_for_each_entry_safe ( packets , tp , & t - > packet_streams , table_entry ) {
list_for_each_entry_safe ( packets , tp , & t - > packet_streams , table_entry ) {
_ write_lock( & packets - > lock ) ;
write_lock( & packets - > lock ) ;
packets - > table_id = - 1 ;
packets - > table_id = - 1 ;
idx = packets - > idx ;
idx = packets - > idx ;
_ write_unlock( & packets - > lock ) ;
write_unlock( & packets - > lock ) ;
_ write_lock( & media_player_lock ) ;
write_lock( & media_player_lock ) ;
if ( stream_packets [ idx ] = = packets ) {
if ( stream_packets [ idx ] = = packets ) {
stream_packets [ idx ] = NULL ;
stream_packets [ idx ] = NULL ;
unref_packet_stream ( packets ) ;
unref_packet_stream ( packets ) ;
}
}
_ write_unlock( & media_player_lock ) ;
write_unlock( & media_player_lock ) ;
unref_packet_stream ( packets ) ;
unref_packet_stream ( packets ) ;
}
}
}
}
@ -3853,13 +3772,13 @@ static void shut_all_threads(void) {
unsigned int nt ;
unsigned int nt ;
struct timer_thread * * thr ;
struct timer_thread * * thr ;
_ write_lock( & media_player_lock ) ;
write_lock( & media_player_lock ) ;
thr = timer_threads ;
thr = timer_threads ;
nt = num_timer_threads ;
nt = num_timer_threads ;
timer_threads = NULL ;
timer_threads = NULL ;
num_timer_threads = 0 ;
num_timer_threads = 0 ;
_ write_unlock( & media_player_lock ) ;
write_unlock( & media_player_lock ) ;
shut_threads ( thr , nt ) ;
shut_threads ( thr , nt ) ;
}
}
@ -3876,10 +3795,10 @@ static void free_packet_stream(struct play_stream_packets *stream) {
if ( stream - > table_id ! = - 1 & & ! list_empty ( & stream - > table_entry ) ) {
if ( stream - > table_id ! = - 1 & & ! list_empty ( & stream - > table_entry ) ) {
t = get_table ( stream - > table_id ) ;
t = get_table ( stream - > table_id ) ;
if ( t ) {
if ( t ) {
_ spin_lock( & t - > player_lock ) ;
spin_lock( & t - > player_lock ) ;
list_del_init ( & stream - > table_entry ) ;
list_del_init ( & stream - > table_entry ) ;
t - > num_packet_streams - - ;
t - > num_packet_streams - - ;
_ spin_unlock( & t - > player_lock ) ;
spin_unlock( & t - > player_lock ) ;
table_put ( t ) ;
table_put ( t ) ;
}
}
}
}
@ -3901,7 +3820,7 @@ static ktime_t play_stream_packet_time(struct play_stream *stream, struct play_s
static void play_stream_next_packet ( struct play_stream * stream ) {
static void play_stream_next_packet ( struct play_stream * stream ) {
struct play_stream_packet * packet = stream - > position ;
struct play_stream_packet * packet = stream - > position ;
struct play_stream_packets * packets = stream - > packets ;
struct play_stream_packets * packets = stream - > packets ;
_ read_lock( & packets - > lock ) ;
read_lock( & packets - > lock ) ;
stream - > position = list_is_last ( & packet - > list , & packets - > packets ) ? NULL : list_next_entry ( packet , list ) ;
stream - > position = list_is_last ( & packet - > list , & packets - > packets ) ? NULL : list_next_entry ( packet , list ) ;
if ( ! stream - > position ) {
if ( ! stream - > position ) {
if ( stream - > info . repeat > 1 ) {
if ( stream - > info . repeat > 1 ) {
@ -3912,7 +3831,7 @@ static void play_stream_next_packet(struct play_stream *stream) {
stream - > info . seq + = packet - > seq + 1 ;
stream - > info . seq + = packet - > seq + 1 ;
}
}
}
}
_ read_unlock( & packets - > lock ) ;
read_unlock( & packets - > lock ) ;
}
}
// stream must be locked, started, and non-empty
// stream must be locked, started, and non-empty
@ -3943,7 +3862,7 @@ static void play_stream_schedule_packet_to_thread(struct play_stream *stream, st
//printk(KERN_WARNING "scheduling packet %u on thread %u\n", packet->seq, tt->idx);
//printk(KERN_WARNING "scheduling packet %u on thread %u\n", packet->seq, tt->idx);
//printk(KERN_WARNING "scheduling stream %p on thread %p (sleeper %i)\n", stream, tt, sleeper);
//printk(KERN_WARNING "scheduling stream %p on thread %p (sleeper %i)\n", stream, tt, sleeper);
_ spin_lock( & tt - > tree_lock ) ;
spin_lock( & tt - > tree_lock ) ;
if ( reschedule & & ! tt - > scheduled & & ! tt - > tree_added ) {
if ( reschedule & & ! tt - > scheduled & & ! tt - > tree_added ) {
// we know we are next. remember this
// we know we are next. remember this
@ -3970,7 +3889,7 @@ static void play_stream_schedule_packet_to_thread(struct play_stream *stream, st
stream - > timer_thread = tt ;
stream - > timer_thread = tt ;
_ spin_unlock( & tt - > tree_lock ) ;
spin_unlock( & tt - > tree_lock ) ;
}
}
// stream must be locked, started, and non-empty
// stream must be locked, started, and non-empty
@ -3982,10 +3901,10 @@ static void play_stream_schedule_packet(struct play_stream *stream) {
unsigned int idx ;
unsigned int idx ;
// XXX check if already scheduled
// XXX check if already scheduled
_ read_lock( & media_player_lock ) ;
read_lock( & media_player_lock ) ;
idx = atomic_fetch_add ( 1 , & last_timer_thread_idx ) % num_timer_threads ;
idx = atomic_fetch_add ( 1 , & last_timer_thread_idx ) % num_timer_threads ;
tt = timer_threads [ idx ] ;
tt = timer_threads [ idx ] ;
_ read_unlock( & media_player_lock ) ;
read_unlock( & media_player_lock ) ;
play_stream_schedule_packet_to_thread ( stream , tt , false ) ;
play_stream_schedule_packet_to_thread ( stream , tt , false ) ;
@ -4059,7 +3978,7 @@ static int timer_worker(void *p) {
//printk(KERN_WARNING "cpu %u (%p) loop enter\n", smp_processor_id(), tt);
//printk(KERN_WARNING "cpu %u (%p) loop enter\n", smp_processor_id(), tt);
_ spin_lock( & tt - > tree_lock ) ;
spin_lock( & tt - > tree_lock ) ;
// grab and remove next scheduled stream, either from predetermined entry or from tree
// grab and remove next scheduled stream, either from predetermined entry or from tree
stream = tt - > scheduled ;
stream = tt - > scheduled ;
if ( ! stream ) {
if ( ! stream ) {
@ -4074,7 +3993,7 @@ static int timer_worker(void *p) {
}
}
tt - > tree_added = false ; // we're up to date before unlock
tt - > tree_added = false ; // we're up to date before unlock
_ spin_unlock( & tt - > tree_lock ) ;
spin_unlock( & tt - > tree_lock ) ;
sleeptime_ns = 500000000LL ; // 0.5 seconds
sleeptime_ns = 500000000LL ; // 0.5 seconds
if ( stream ) {
if ( stream ) {
@ -4082,11 +4001,11 @@ static int timer_worker(void *p) {
now = ktime_get ( ) ;
now = ktime_get ( ) ;
_ spin_lock( & stream - > lock ) ;
spin_lock( & stream - > lock ) ;
if ( stream - > table_id = = - 1 ) {
if ( stream - > table_id = = - 1 ) {
// we've been descheduled
// we've been descheduled
_ spin_unlock( & stream - > lock ) ;
spin_unlock( & stream - > lock ) ;
unref_play_stream ( stream ) ;
unref_play_stream ( stream ) ;
continue ;
continue ;
}
}
@ -4102,12 +4021,12 @@ static int timer_worker(void *p) {
//printk(KERN_WARNING "cpu %u sending packet %p from stream %p now\n",
//printk(KERN_WARNING "cpu %u sending packet %p from stream %p now\n",
//smp_processor_id(), packet, stream);
//smp_processor_id(), packet, stream);
_ spin_unlock( & stream - > lock ) ;
spin_unlock( & stream - > lock ) ;
//printk(KERN_WARNING "cpu %u sending packet %u now\n", tt->idx, packet->seq);
//printk(KERN_WARNING "cpu %u sending packet %u now\n", tt->idx, packet->seq);
play_stream_send_packet ( stream , packet ) ;
play_stream_send_packet ( stream , packet ) ;
_ spin_lock( & stream - > lock ) ;
spin_lock( & stream - > lock ) ;
if ( stream - > table_id ! = - 1 )
if ( stream - > table_id ! = - 1 )
play_stream_next_packet ( stream ) ;
play_stream_next_packet ( stream ) ;
@ -4119,25 +4038,25 @@ static int timer_worker(void *p) {
if ( stream - > position ) {
if ( stream - > position ) {
play_stream_schedule_packet_to_thread ( stream , tt , false ) ;
play_stream_schedule_packet_to_thread ( stream , tt , false ) ;
sleeptime_ns = 0 ; // loop and get next packet from tree
sleeptime_ns = 0 ; // loop and get next packet from tree
_ spin_unlock( & stream - > lock ) ;
spin_unlock( & stream - > lock ) ;
unref_play_stream ( stream ) ;
unref_play_stream ( stream ) ;
stream = NULL ;
stream = NULL ;
}
}
else {
else {
// end of stream
// end of stream
if ( ! stream - > info . remove_at_end )
if ( ! stream - > info . remove_at_end )
_ spin_unlock( & stream - > lock ) ;
spin_unlock( & stream - > lock ) ;
else {
else {
// remove it
// remove it
end_of_stream ( stream ) ;
end_of_stream ( stream ) ;
_ spin_unlock( & stream - > lock ) ;
spin_unlock( & stream - > lock ) ;
_ write_lock( & media_player_lock ) ;
write_lock( & media_player_lock ) ;
if ( play_streams [ stream - > idx ] = = stream ) {
if ( play_streams [ stream - > idx ] = = stream ) {
play_streams [ stream - > idx ] = NULL ;
play_streams [ stream - > idx ] = NULL ;
unref_play_stream ( stream ) ;
unref_play_stream ( stream ) ;
}
}
// else log error?
// else log error?
_ write_unlock( & media_player_lock ) ;
write_unlock( & media_player_lock ) ;
}
}
unref_play_stream ( stream ) ;
unref_play_stream ( stream ) ;
stream = NULL ;
stream = NULL ;
@ -4156,7 +4075,7 @@ static int timer_worker(void *p) {
//tt->idx);
//tt->idx);
// return packet to tree
// return packet to tree
play_stream_schedule_packet_to_thread ( stream , tt , true ) ;
play_stream_schedule_packet_to_thread ( stream , tt , true ) ;
_ spin_unlock( & stream - > lock ) ;
spin_unlock( & stream - > lock ) ;
sleeptime_ns = min ( sleeptime_ns , ns_diff ) ;
sleeptime_ns = min ( sleeptime_ns , ns_diff ) ;
unref_play_stream ( stream ) ;
unref_play_stream ( stream ) ;
stream = NULL ;
stream = NULL ;
@ -4202,7 +4121,7 @@ static struct timer_thread *launch_thread(unsigned int cpu) {
kfree ( tt ) ;
kfree ( tt ) ;
return ERR_PTR ( ret ) ;
return ERR_PTR ( ret ) ;
}
}
_ spin_lock_init( & tt - > tree_lock ) ;
spin_lock_init( & tt - > tree_lock ) ;
tt - > idx = cpu ;
tt - > idx = cpu ;
tt - > task = kthread_create_on_node ( timer_worker , tt , cpu_to_node ( cpu ) , " rtpengine_%u " , cpu ) ;
tt - > task = kthread_create_on_node ( timer_worker , tt , cpu_to_node ( cpu ) , " rtpengine_%u " , cpu ) ;
if ( IS_ERR ( tt - > task ) ) {
if ( IS_ERR ( tt - > task ) ) {
@ -4226,14 +4145,14 @@ static int init_play_streams(unsigned int n_play_streams, unsigned int n_stream_
struct play_stream_packets * * new_stream_packets , * * old_stream_packets = NULL ;
struct play_stream_packets * * new_stream_packets , * * old_stream_packets = NULL ;
unsigned int cpu ;
unsigned int cpu ;
_ write_lock( & media_player_lock ) ;
write_lock( & media_player_lock ) ;
if ( num_play_streams > = n_play_streams & & num_stream_packets > = n_stream_packets )
if ( num_play_streams > = n_play_streams & & num_stream_packets > = n_stream_packets )
goto out ;
goto out ;
need_threads = timer_threads = = NULL ;
need_threads = timer_threads = = NULL ;
_ write_unlock( & media_player_lock ) ;
write_unlock( & media_player_lock ) ;
//printk(KERN_WARNING "allocating for %u/%u -> %u/%u streams\n",
//printk(KERN_WARNING "allocating for %u/%u -> %u/%u streams\n",
//num_play_streams, n_play_streams,
//num_play_streams, n_play_streams,
@ -4267,7 +4186,7 @@ static int init_play_streams(unsigned int n_play_streams, unsigned int n_stream_
}
}
}
}
_ write_lock( & media_player_lock ) ;
write_lock( & media_player_lock ) ;
// check again
// check again
ret = 0 ;
ret = 0 ;
@ -4292,7 +4211,7 @@ static int init_play_streams(unsigned int n_play_streams, unsigned int n_stream_
}
}
out :
out :
_ write_unlock( & media_player_lock ) ;
write_unlock( & media_player_lock ) ;
err :
err :
shut_threads ( threads_new , new_num_threads ) ;
shut_threads ( threads_new , new_num_threads ) ;
kfree ( old_play_streams ) ;
kfree ( old_play_streams ) ;
@ -4311,22 +4230,22 @@ static int get_packet_stream(struct rtpengine_table *t, unsigned int *num) {
INIT_LIST_HEAD ( & new_stream - > packets ) ;
INIT_LIST_HEAD ( & new_stream - > packets ) ;
INIT_LIST_HEAD ( & new_stream - > table_entry ) ;
INIT_LIST_HEAD ( & new_stream - > table_entry ) ;
_ rwlock_init( & new_stream - > lock ) ;
rwlock_init( & new_stream - > lock ) ;
new_stream - > table_id = t - > id ;
new_stream - > table_id = t - > id ;
atomic_set ( & new_stream - > refcnt , 1 ) ;
atomic_set ( & new_stream - > refcnt , 1 ) ;
for ( i = 0 ; i < num_stream_packets ; i + + ) {
for ( i = 0 ; i < num_stream_packets ; i + + ) {
_ write_lock( & media_player_lock ) ;
write_lock( & media_player_lock ) ;
idx = atomic_fetch_add ( 1 , & last_stream_packets_idx ) % num_stream_packets ;
idx = atomic_fetch_add ( 1 , & last_stream_packets_idx ) % num_stream_packets ;
if ( stream_packets [ idx ] ) {
if ( stream_packets [ idx ] ) {
idx = - 1 ;
idx = - 1 ;
_ write_unlock( & media_player_lock ) ;
write_unlock( & media_player_lock ) ;
continue ;
continue ;
}
}
stream_packets [ idx ] = new_stream ;
stream_packets [ idx ] = new_stream ;
new_stream - > idx = idx ;
new_stream - > idx = idx ;
ref_packet_stream ( new_stream ) ;
ref_packet_stream ( new_stream ) ;
_ write_unlock( & media_player_lock ) ;
write_unlock( & media_player_lock ) ;
break ;
break ;
}
}
@ -4335,13 +4254,13 @@ static int get_packet_stream(struct rtpengine_table *t, unsigned int *num) {
return - EBUSY ;
return - EBUSY ;
}
}
_ spin_lock( & t - > player_lock ) ;
spin_lock( & t - > player_lock ) ;
list_add ( & new_stream - > table_entry , & t - > packet_streams ) ;
list_add ( & new_stream - > table_entry , & t - > packet_streams ) ;
// hand over ref
// hand over ref
new_stream = NULL ;
new_stream = NULL ;
t - > num_packet_streams + + ;
t - > num_packet_streams + + ;
// XXX race between adding to list and stop/free?
// XXX race between adding to list and stop/free?
_ spin_unlock( & t - > player_lock ) ;
spin_unlock( & t - > player_lock ) ;
* num = idx ;
* num = idx ;
return 0 ;
return 0 ;
@ -4377,7 +4296,7 @@ static int play_stream_packet(const struct rtpengine_play_stream_packet_info *in
//printk(KERN_WARNING "new packet %p, delay %ld us\n", packet, (long int) ktime_to_us(packet->delay));
//printk(KERN_WARNING "new packet %p, delay %ld us\n", packet, (long int) ktime_to_us(packet->delay));
// XXX alloc skb
// XXX alloc skb
_ read_lock( & media_player_lock ) ;
read_lock( & media_player_lock ) ;
ret = - ERANGE ;
ret = - ERANGE ;
if ( info - > packet_stream_idx > = num_stream_packets )
if ( info - > packet_stream_idx > = num_stream_packets )
@ -4388,12 +4307,12 @@ static int play_stream_packet(const struct rtpengine_play_stream_packet_info *in
if ( ! stream )
if ( ! stream )
goto out ;
goto out ;
_ write_lock( & stream - > lock ) ;
write_lock( & stream - > lock ) ;
if ( ! list_empty ( & stream - > packets ) ) {
if ( ! list_empty ( & stream - > packets ) ) {
last = list_last_entry ( & stream - > packets , struct play_stream_packet , list ) ;
last = list_last_entry ( & stream - > packets , struct play_stream_packet , list ) ;
if ( ktime_after ( last - > delay , packet - > delay ) ) {
if ( ktime_after ( last - > delay , packet - > delay ) ) {
_ write_unlock( & stream - > lock ) ;
write_unlock( & stream - > lock ) ;
ret = - ELOOP ;
ret = - ELOOP ;
goto out ;
goto out ;
}
}
@ -4402,12 +4321,12 @@ static int play_stream_packet(const struct rtpengine_play_stream_packet_info *in
packet - > seq = stream - > len ;
packet - > seq = stream - > len ;
stream - > len + + ;
stream - > len + + ;
_ write_unlock( & stream - > lock ) ;
write_unlock( & stream - > lock ) ;
packet = NULL ;
packet = NULL ;
ret = 0 ;
ret = 0 ;
out :
out :
_ read_unlock( & media_player_lock ) ;
read_unlock( & media_player_lock ) ;
if ( packet )
if ( packet )
free_play_stream_packet ( packet ) ;
free_play_stream_packet ( packet ) ;
return ret ;
return ret ;
@ -4451,14 +4370,14 @@ static int play_stream(struct rtpengine_table *t, const struct rtpengine_play_st
play_stream - > info = * info ;
play_stream - > info = * info ;
play_stream - > table_id = t - > id ;
play_stream - > table_id = t - > id ;
atomic_set ( & play_stream - > refcnt , 1 ) ;
atomic_set ( & play_stream - > refcnt , 1 ) ;
_ spin_lock_init( & play_stream - > lock ) ;
spin_lock_init( & play_stream - > lock ) ;
play_stream - > info . stats = stats ;
play_stream - > info . stats = stats ;
play_stream - > info . iface_stats = iface_stats ;
play_stream - > info . iface_stats = iface_stats ;
play_stream - > info . ssrc_stats = ssrc_stats ;
play_stream - > info . ssrc_stats = ssrc_stats ;
ret = 0 ;
ret = 0 ;
_ read_lock( & media_player_lock ) ;
read_lock( & media_player_lock ) ;
if ( info - > packet_stream_idx > = num_stream_packets )
if ( info - > packet_stream_idx > = num_stream_packets )
ret = - ERANGE ;
ret = - ERANGE ;
@ -4470,38 +4389,38 @@ static int play_stream(struct rtpengine_table *t, const struct rtpengine_play_st
ref_packet_stream ( packets ) ;
ref_packet_stream ( packets ) ;
}
}
_ read_unlock( & media_player_lock ) ;
read_unlock( & media_player_lock ) ;
if ( ret )
if ( ret )
goto out ;
goto out ;
_ read_lock( & packets - > lock ) ;
read_lock( & packets - > lock ) ;
ret = - ENXIO ;
ret = - ENXIO ;
if ( list_empty ( & packets - > packets ) ) {
if ( list_empty ( & packets - > packets ) ) {
_ read_unlock( & packets - > lock ) ;
read_unlock( & packets - > lock ) ;
goto out ;
goto out ;
}
}
play_stream - > packets = packets ;
play_stream - > packets = packets ;
play_stream - > position = list_first_entry ( & packets - > packets , struct play_stream_packet , list ) ;
play_stream - > position = list_first_entry ( & packets - > packets , struct play_stream_packet , list ) ;
_ read_unlock( & packets - > lock ) ;
read_unlock( & packets - > lock ) ;
packets = NULL ; // ref handed over
packets = NULL ; // ref handed over
for ( i = 0 ; i < num_play_streams ; i + + ) {
for ( i = 0 ; i < num_play_streams ; i + + ) {
_ write_lock( & media_player_lock ) ;
write_lock( & media_player_lock ) ;
idx = atomic_fetch_add ( 1 , & last_play_stream_idx ) % num_play_streams ;
idx = atomic_fetch_add ( 1 , & last_play_stream_idx ) % num_play_streams ;
if ( play_streams [ idx ] ) {
if ( play_streams [ idx ] ) {
_ write_unlock( & media_player_lock ) ;
write_unlock( & media_player_lock ) ;
idx = - 1 ;
idx = - 1 ;
continue ;
continue ;
}
}
play_streams [ idx ] = play_stream ;
play_streams [ idx ] = play_stream ;
ref_play_stream ( play_stream ) ;
ref_play_stream ( play_stream ) ;
play_stream - > idx = idx ;
play_stream - > idx = idx ;
_ write_unlock( & media_player_lock ) ;
write_unlock( & media_player_lock ) ;
break ;
break ;
}
}
@ -4509,27 +4428,27 @@ static int play_stream(struct rtpengine_table *t, const struct rtpengine_play_st
if ( idx = = - 1 )
if ( idx = = - 1 )
goto out ;
goto out ;
_ spin_lock( & t - > player_lock ) ;
spin_lock( & t - > player_lock ) ;
list_add ( & play_stream - > table_entry , & t - > play_streams ) ;
list_add ( & play_stream - > table_entry , & t - > play_streams ) ;
ref_play_stream ( play_stream ) ;
ref_play_stream ( play_stream ) ;
t - > num_play_streams + + ;
t - > num_play_streams + + ;
// XXX race between adding to list and stop/free?
// XXX race between adding to list and stop/free?
_ spin_unlock( & t - > player_lock ) ;
spin_unlock( & t - > player_lock ) ;
_ spin_lock( & play_stream - > lock ) ;
spin_lock( & play_stream - > lock ) ;
play_stream - > start_time = ktime_get ( ) ;
play_stream - > start_time = ktime_get ( ) ;
crypto_context_init ( & play_stream - > encrypt , & info - > encrypt ) ;
crypto_context_init ( & play_stream - > encrypt , & info - > encrypt ) ;
ret = gen_rtp_session_keys ( & play_stream - > encrypt , & info - > encrypt ) ;
ret = gen_rtp_session_keys ( & play_stream - > encrypt , & info - > encrypt ) ;
if ( ret ) {
if ( ret ) {
_ spin_unlock( & play_stream - > lock ) ;
spin_unlock( & play_stream - > lock ) ;
goto out ;
goto out ;
}
}
//printk(KERN_WARNING "start time %ld us\n", (long int) ktime_to_us(play_stream->start_time));
//printk(KERN_WARNING "start time %ld us\n", (long int) ktime_to_us(play_stream->start_time));
play_stream_schedule_packet ( play_stream ) ;
play_stream_schedule_packet ( play_stream ) ;
_ spin_unlock( & play_stream - > lock ) ;
spin_unlock( & play_stream - > lock ) ;
* num = idx ;
* num = idx ;
ret = 0 ;
ret = 0 ;
@ -4550,10 +4469,10 @@ static void end_of_stream(struct play_stream *stream) {
t = get_table ( stream - > table_id ) ;
t = get_table ( stream - > table_id ) ;
if ( t ) {
if ( t ) {
//printk(KERN_WARNING "removing stream %p from table\n", stream);
//printk(KERN_WARNING "removing stream %p from table\n", stream);
_ spin_lock( & t - > player_lock ) ;
spin_lock( & t - > player_lock ) ;
list_del_init ( & stream - > table_entry ) ;
list_del_init ( & stream - > table_entry ) ;
t - > num_play_streams - - ;
t - > num_play_streams - - ;
_ spin_unlock( & t - > player_lock ) ;
spin_unlock( & t - > player_lock ) ;
table_put ( t ) ;
table_put ( t ) ;
unref_play_stream ( stream ) ;
unref_play_stream ( stream ) ;
}
}
@ -4568,7 +4487,7 @@ static void do_stop_stream(struct play_stream *stream) {
//printk(KERN_WARNING "stop stream %p\n", stream);
//printk(KERN_WARNING "stop stream %p\n", stream);
_ spin_lock( & stream - > lock ) ;
spin_lock( & stream - > lock ) ;
end_of_stream ( stream ) ;
end_of_stream ( stream ) ;
@ -4576,7 +4495,7 @@ static void do_stop_stream(struct play_stream *stream) {
stream - > timer_thread = NULL ;
stream - > timer_thread = NULL ;
if ( tt ) {
if ( tt ) {
_ spin_lock( & tt - > tree_lock ) ;
spin_lock( & tt - > tree_lock ) ;
if ( tt - > scheduled = = stream ) {
if ( tt - > scheduled = = stream ) {
//printk(KERN_WARNING "stream %p was scheduled\n", stream);
//printk(KERN_WARNING "stream %p was scheduled\n", stream);
@ -4595,10 +4514,10 @@ static void do_stop_stream(struct play_stream *stream) {
}
}
}
}
_ spin_unlock( & tt - > tree_lock ) ;
spin_unlock( & tt - > tree_lock ) ;
}
}
_ spin_unlock( & stream - > lock ) ;
spin_unlock( & stream - > lock ) ;
}
}
static int stop_stream ( struct rtpengine_table * t , unsigned int num ) {
static int stop_stream ( struct rtpengine_table * t , unsigned int num ) {
@ -4607,7 +4526,7 @@ static int stop_stream(struct rtpengine_table *t, unsigned int num) {
ret = 0 ;
ret = 0 ;
_ write_lock( & media_player_lock ) ;
write_lock( & media_player_lock ) ;
if ( num > = num_play_streams )
if ( num > = num_play_streams )
ret = - ERANGE ;
ret = - ERANGE ;
@ -4619,7 +4538,7 @@ static int stop_stream(struct rtpengine_table *t, unsigned int num) {
play_streams [ num ] = NULL ; ;
play_streams [ num ] = NULL ; ;
}
}
_ write_unlock( & media_player_lock ) ;
write_unlock( & media_player_lock ) ;
if ( ret )
if ( ret )
return ret ;
return ret ;
@ -4627,14 +4546,14 @@ static int stop_stream(struct rtpengine_table *t, unsigned int num) {
do_stop_stream ( stream ) ;
do_stop_stream ( stream ) ;
// check if stream was released, wait if it wasn't
// check if stream was released, wait if it wasn't
_ spin_lock( & stream - > lock ) ;
spin_lock( & stream - > lock ) ;
while ( stream - > timer_thread ) {
while ( stream - > timer_thread ) {
_ spin_unlock( & stream - > lock ) ;
spin_unlock( & stream - > lock ) ;
cpu_relax ( ) ;
cpu_relax ( ) ;
schedule ( ) ;
schedule ( ) ;
_ spin_lock( & stream - > lock ) ;
spin_lock( & stream - > lock ) ;
}
}
_ spin_unlock( & stream - > lock ) ;
spin_unlock( & stream - > lock ) ;
unref_play_stream ( stream ) ;
unref_play_stream ( stream ) ;
@ -4645,7 +4564,7 @@ static int cmd_free_packet_stream(struct rtpengine_table *t, unsigned int idx) {
struct play_stream_packets * stream = NULL ;
struct play_stream_packets * stream = NULL ;
int ret ;
int ret ;
_ write_lock( & media_player_lock ) ;
write_lock( & media_player_lock ) ;
ret = - ERANGE ;
ret = - ERANGE ;
if ( idx > = num_stream_packets )
if ( idx > = num_stream_packets )
@ -4662,30 +4581,30 @@ static int cmd_free_packet_stream(struct rtpengine_table *t, unsigned int idx) {
ret = 0 ;
ret = 0 ;
out :
out :
_ write_unlock( & media_player_lock ) ;
write_unlock( & media_player_lock ) ;
if ( ! stream )
if ( ! stream )
return ret ;
return ret ;
_ write_lock( & stream - > lock ) ;
write_lock( & stream - > lock ) ;
idx = stream - > idx ;
idx = stream - > idx ;
stream - > table_id = - 1 ;
stream - > table_id = - 1 ;
_ write_unlock( & stream - > lock ) ;
write_unlock( & stream - > lock ) ;
if ( idx ! = - 1 ) {
if ( idx ! = - 1 ) {
_ write_lock( & media_player_lock ) ;
write_lock( & media_player_lock ) ;
if ( stream_packets [ idx ] = = stream ) {
if ( stream_packets [ idx ] = = stream ) {
stream_packets [ idx ] = NULL ;
stream_packets [ idx ] = NULL ;
unref_packet_stream ( stream ) ;
unref_packet_stream ( stream ) ;
}
}
_ write_unlock( & media_player_lock ) ;
write_unlock( & media_player_lock ) ;
}
}
if ( ! list_empty ( & stream - > table_entry ) ) {
if ( ! list_empty ( & stream - > table_entry ) ) {
_ spin_lock( & t - > player_lock ) ;
spin_lock( & t - > player_lock ) ;
list_del_init ( & stream - > table_entry ) ;
list_del_init ( & stream - > table_entry ) ;
t - > num_packet_streams - - ;
t - > num_packet_streams - - ;
_ spin_unlock( & t - > player_lock ) ;
spin_unlock( & t - > player_lock ) ;
unref_packet_stream ( stream ) ;
unref_packet_stream ( stream ) ;
}
}
@ -6724,7 +6643,7 @@ static int __init init(void) {
goto fail ;
goto fail ;
# ifdef KERNEL_PLAYER
# ifdef KERNEL_PLAYER
_ rwlock_init( & media_player_lock ) ;
rwlock_init( & media_player_lock ) ;
# endif
# endif
return 0 ;
return 0 ;