ps2sdk  1.1
A collection of Open Source libraries used for developing applications on Sony's PlayStation 2® (PS2).
sleep.c
Go to the documentation of this file.
1 /*
2 # _____ ___ ____ ___ ____
3 # ____| | ____| | | |____|
4 # | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
5 #-----------------------------------------------------------------------
6 # Copyright 2001-2005, ps2dev - http://www.ps2dev.org
7 # Licenced under Academic Free License version 2.0
8 # Review ps2sdk README & LICENSE files for further details.
9 */
10 
16 #include <kernel.h>
17 
18 #include <errno.h>
19 #include <time.h>
20 #include <unistd.h>
21 
22 #include "ps2sdkapi.h"
23 
24 #define MIN_HSYNC_PER_SEC (240*50)
25 #define MIN_HSYNC_DELAY 100
26 #define MAX_PS2CLOCK_PER_HSYNC (PS2_CLOCKS_PER_SEC/MIN_HSYNC_PER_SEC)
27 
28 // Start with the highest possible value (so we sleep too short)
30 
31 static void _sleep_waker(s32 alarm_id, u16 time, void *arg2)
32 {
33  s32 *pSema = (s32 *)arg2;
34  iSignalSema(*pSema);
35  ExitHandler();
36 }
37 
38 static inline u64 timespec_to_us(const struct timespec *pts) {
39  return (pts->tv_sec * 1000000ULL) + (pts->tv_nsec / 1000ULL);
40 }
41 
42 static inline ps2_clock_t us_to_ps2_clock(u64 us) {
43  return (us * PS2_CLOCKS_PER_MSEC) / 1000;
44 }
45 
46 static inline ps2_clock_t timespec_to_ps2_clock(const struct timespec *pts) {
47  return us_to_ps2_clock(timespec_to_us(pts));
48 }
49 
50 int nanosleep(const struct timespec *req, struct timespec *rem)
51 {
52  ee_sema_t sema;
53  s32 sema_id;
54  ps2_clock_t clock_delay, clock_end, clock_real_end;
55  u16 hsync_delay;
56 
57  clock_delay = timespec_to_ps2_clock(req);
58  clock_end = ps2_clock() + clock_delay;
59  hsync_delay = clock_delay / iPS2ClockPerHSync;
60 
61  if (hsync_delay >= MIN_HSYNC_DELAY) {
62  sema.init_count = 0;
63  sema.max_count = 1;
64  sema.option = 0;
65  sema_id = CreateSema(&sema);
66 
67  SetAlarm(hsync_delay, _sleep_waker, &sema_id);
68  WaitSema(sema_id);
69  DeleteSema(sema_id);
70 
71  // Correct the HSync delay
72  // NOTE: We're always trying to end btween 0 and 1 HSyncs too short
73  clock_real_end = ps2_clock();
74  if (clock_real_end < (clock_end - iPS2ClockPerHSync)) {
75  // We sleeped too short, so HSyncs must be faster
76  // Correct the HSyncs for next time
77  iPS2ClockPerHSync -= (clock_end - iPS2ClockPerHSync - clock_real_end) / hsync_delay;
78  }
79  else if (clock_real_end > clock_end) {
80  // We sleeped too long, so HSyncs must be slower
81  // Correct the HSyncs for next time
82  iPS2ClockPerHSync += (clock_real_end - clock_end) / (hsync_delay-1);
83  }
84  }
85 
86  // Delay whatever time is left
87  while(clock_end > ps2_clock())
88  ;
89 
90  if (rem != NULL) {
91  rem->tv_sec = 0;
92  rem->tv_nsec = 0;
93  }
94 
95  return 0;
96 }
97 
98 unsigned int sleep(unsigned int seconds)
99 {
100  struct timespec ts;
101 
102  ts.tv_sec = seconds;
103  ts.tv_nsec = 0;
104 
105  if (!nanosleep(&ts, &ts))
106  return 0;
107 
108  if (errno == EINTR)
109  return ts.tv_sec;
110 
111  return -1;
112 }
#define EINTR
Definition: errno.h:26
s32 CreateSema(ee_sema_t *sema)
#define ExitHandler()
Definition: kernel.h:28
s32 DeleteSema(s32 sema_id)
s32 iSignalSema(s32 sema_id)
s32 WaitSema(s32 sema_id)
int errno
s32 SetAlarm(u16 time, void(*callback)(s32 alarm_id, u16 time, void *common), void *common)
u32 time
Definition: libmouse.c:37
uint64_t ps2_clock_t
Definition: ps2sdkapi.h:41
#define PS2_CLOCKS_PER_MSEC
Definition: ps2sdkapi.h:39
ps2_clock_t ps2_clock(void)
int nanosleep(const struct timespec *req, struct timespec *rem)
Definition: sleep.c:50
unsigned int sleep(unsigned int seconds)
Definition: sleep.c:98
#define MIN_HSYNC_DELAY
Definition: sleep.c:25
static ps2_clock_t us_to_ps2_clock(u64 us)
Definition: sleep.c:42
static ps2_clock_t timespec_to_ps2_clock(const struct timespec *pts)
Definition: sleep.c:46
static u64 timespec_to_us(const struct timespec *pts)
Definition: sleep.c:38
static void _sleep_waker(s32 alarm_id, u16 time, void *arg2)
Definition: sleep.c:31
static unsigned int iPS2ClockPerHSync
Definition: sleep.c:29
#define MAX_PS2CLOCK_PER_HSYNC
Definition: sleep.c:26
int init_count
Definition: kernel.h:218
int max_count
Definition: kernel.h:217
u32 option
Definition: kernel.h:221
#define NULL
Definition: tamtypes.h:91
signed int s32
Definition: tamtypes.h:58
unsigned short u16
Definition: tamtypes.h:24
unsigned long u64
Definition: tamtypes.h:34