A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 213 lines 7.1 kB view raw
1/*************************************************************************** 2 * __________ __ ___. 3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 * \/ \/ \/ \/ \/ 8 * $Id$ 9 * 10 * Copyright (C) 2002 by Ulf Ralberg 11 * 12 * This program is free software; you can redistribute it and/or 13 * modify it under the terms of the GNU General Public License 14 * as published by the Free Software Foundation; either version 2 15 * of the License, or (at your option) any later version. 16 * 17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 18 * KIND, either express or implied. 19 * 20 ****************************************************************************/ 21#ifndef THREAD_H 22#define THREAD_H 23 24#include <inttypes.h> 25#include <stddef.h> 26#include <stdbool.h> 27#include "config.h" 28#include "gcc_extensions.h" 29#include "linked_list.h" 30#include "bitarray.h" 31#include "corelock.h" 32 33/* Priority scheduling (when enabled with HAVE_PRIORITY_SCHEDULING) works 34 * by giving high priority threads more CPU time than lower priority threads 35 * when they need it. Priority is differential such that the priority 36 * difference between a lower priority runnable thread and the highest priority 37 * runnable thread determines the amount of aging necessary for the lower 38 * priority thread to be scheduled in order to prevent starvation. 39 * 40 * If software playback codec pcm buffer is going down to critical, codec 41 * can gradually raise its own priority to override user interface and 42 * prevent playback skipping. 43 */ 44#define PRIORITY_RESERVED_HIGH 0 /* Reserved */ 45#define PRIORITY_RESERVED_LOW 32 /* Reserved */ 46#define HIGHEST_PRIORITY 1 /* The highest possible thread priority */ 47#define LOWEST_PRIORITY 31 /* The lowest possible thread priority */ 48/* Realtime range reserved for threads that will not allow threads of lower 49 * priority to age and run (future expansion) */ 50#define PRIORITY_REALTIME_1 1 51#define PRIORITY_REALTIME_2 2 52#define PRIORITY_REALTIME_3 3 53#define PRIORITY_REALTIME_4 4 54#define PRIORITY_REALTIME 4 /* Lowest realtime range */ 55#define PRIORITY_BUFFERING 15 /* Codec buffering thread */ 56#define PRIORITY_USER_INTERFACE 16 /* For most UI thrads */ 57#define PRIORITY_RECORDING 16 /* Recording thread */ 58#define PRIORITY_PLAYBACK 16 /* Variable between this and MAX */ 59#define PRIORITY_PLAYBACK_MAX 5 /* Maximum allowable playback priority */ 60#define PRIORITY_SYSTEM 18 /* All other firmware threads */ 61#define PRIORITY_BACKGROUND 20 /* Normal application threads */ 62#define NUM_PRIORITIES 32 63#define PRIORITY_IDLE 32 /* Priority representative of no tasks */ 64 65#define PRIORITY_MAIN_THREAD PRIORITY_USER_INTERFACE 66#define IO_PRIORITY_IMMEDIATE 0 67#define IO_PRIORITY_BACKGROUND 32 68 69# ifdef HAVE_HARDWARE_CLICK 70# define BASETHREADS 17 71# else 72# define BASETHREADS 16 73# endif 74 75#ifndef TARGET_EXTRA_THREADS 76#define TARGET_EXTRA_THREADS 0 77#endif 78 79#define MAXTHREADS (BASETHREADS+TARGET_EXTRA_THREADS) 80 81BITARRAY_TYPE_DECLARE(threadbit_t, threadbit, MAXTHREADS) 82BITARRAY_TYPE_DECLARE(priobit_t, priobit, NUM_PRIORITIES) 83 84struct thread_entry; 85 86/* 87 * We need more stack when we run under a host 88 * maybe more expensive C lib functions? 89 * 90 * simulator (possibly) doesn't simulate stack usage anyway but well ... */ 91 92#if defined(HAVE_SDL_THREADS) || defined(__PCTOOL__) || defined(CTRU) 93#define DEFAULT_STACK_SIZE 0x100 /* tiny, ignored anyway */ 94#else 95#include "asm/thread.h" 96#endif /* HAVE_SDL_THREADS */ 97 98extern void yield(void); 99extern unsigned sleep(unsigned ticks); 100 101#ifdef HAVE_PRIORITY_SCHEDULING 102#define IF_PRIO(...) __VA_ARGS__ 103#define IFN_PRIO(...) 104#else 105#define IF_PRIO(...) 106#define IFN_PRIO(...) __VA_ARGS__ 107#endif 108 109#define __wait_queue lld_head 110#define __wait_queue_node lld_node 111 112/* Basic structure describing the owner of an object */ 113struct blocker 114{ 115 struct thread_entry * volatile thread; /* thread blocking other threads 116 (aka. object owner) */ 117#ifdef HAVE_PRIORITY_SCHEDULING 118 int priority; /* highest priority waiter */ 119#endif 120}; 121 122/* If a thread has a blocker but the blocker's registered thread is NULL, 123 then it references this and the struct blocker pointer may be 124 reinterpreted as such. */ 125struct blocker_splay 126{ 127 struct blocker blocker; /* blocker info (first!) */ 128#ifdef HAVE_PRIORITY_SCHEDULING 129 threadbit_t mask; /* mask of nonzero tcounts */ 130#if NUM_CORES > 1 131 struct corelock cl; /* mutual exclusion */ 132#endif 133#endif /* HAVE_PRIORITY_SCHEDULING */ 134}; 135 136void core_idle(void); 137void core_wake(IF_COP_VOID(unsigned int core)); 138 139/* Allocate a thread in the scheduler */ 140#define CREATE_THREAD_FROZEN 0x00000001 /* Thread is frozen at create time */ 141unsigned int create_thread(void (*function)(void), 142 void* stack, size_t stack_size, 143 unsigned flags, const char *name 144 IF_PRIO(, int priority) 145 IF_COP(, unsigned int core)); 146 147/* Set and clear the CPU frequency boost flag for the calling thread */ 148#ifdef HAVE_SCHEDULER_BOOSTCTRL 149void trigger_cpu_boost(void); 150void cancel_cpu_boost(void); 151#else 152#define trigger_cpu_boost() do { } while(0) 153#define cancel_cpu_boost() do { } while(0) 154#endif 155/* Make a frozen thread runnable (when started with CREATE_THREAD_FROZEN). 156 * Has no effect on a thread not frozen. */ 157void thread_thaw(unsigned int thread_id); 158/* Wait for a thread to exit */ 159void thread_wait(unsigned int thread_id); 160/* Exit the current thread */ 161void thread_exit(void) NORETURN_ATTR; 162 163#ifdef HAVE_PRIORITY_SCHEDULING 164int thread_set_priority(unsigned int thread_id, int priority); 165int thread_get_priority(unsigned int thread_id); 166#endif /* HAVE_PRIORITY_SCHEDULING */ 167 168#if NUM_CORES > 1 169unsigned int switch_core(unsigned int new_core); 170#endif 171 172/* Return the id of the calling thread. */ 173unsigned int thread_self(void); 174 175/* Debugging info - only! */ 176#if NUM_CORES > 1 177struct core_debug_info 178{ 179 unsigned int idle_stack_usage; 180}; 181 182int core_get_debug_info(unsigned int core, struct core_debug_info *infop); 183 184#endif /* NUM_CORES */ 185 186#ifdef HAVE_SDL_THREADS 187#define IF_SDL(x...) x 188#define IFN_SDL(x...) 189#else 190#define IF_SDL(x...) 191#define IFN_SDL(x...) x 192#endif 193 194struct thread_debug_info 195{ 196 char statusstr[4]; 197 char name[32]; 198#ifndef HAVE_SDL_THREADS 199 unsigned int stack_usage_cur; 200 unsigned int stack_usage; 201#endif 202#if NUM_CORES > 1 203 unsigned int core; 204#endif 205#ifdef HAVE_PRIORITY_SCHEDULING 206 int base_priority; 207 int current_priority; 208#endif 209}; 210int thread_get_debug_info(unsigned int thread_id, 211 struct thread_debug_info *infop); 212 213#endif /* THREAD_H */