1

I've just started learning x86_64 asm and I would like to implement a usleep like procedure without using any syscalls.

extern void my_usleep(int);
my_usleep:
    ; stuff
    ret
Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
weyh
  • 169
  • 2
  • 5
  • 1
    I don't think you can do it without syscalls. You can write a busy loop, but it will need to use a system call to get the current time so it can tell when to stop. – Barmar Nov 04 '22 at 21:14
  • There's the [Time Stamp Counter](https://en.wikipedia.org/wiki/Time_Stamp_Counter) you can read, but (a) it looks like it would be hard to calibrate to actual microseconds and (b) it looks like it's kinda obsolete. – Steve Summit Nov 04 '22 at 21:27
  • 2
    What operating system are you programming for? `usleep` is usually implemented with the `nanosleep` system call these days. – fuz Nov 04 '22 at 21:35
  • 4
    The point of `usleep` / `nanosleep` is to hand control of the CPU back to the OS for some time. A busy-wait spin loop is a different thing, and shouldn't be called a "sleep" because the CPU can't save power or run anything else during it. – Peter Cordes Nov 05 '22 at 01:22
  • 4
    a busy wait loop is called a `delay` in bare metal programming. A sleep does real sleeping – phuclv Nov 05 '22 at 02:49

1 Answers1

4

I've just started learning x86_64 asm and I would like to implement a usleep like procedure without using any syscalls.

Without using any system calls; the only viable option would be a busy loop relying on the timestamp from either the rdtsc or rdtscp instruction.

This involves converting the delay from microseconds into whatever the CPU's TSC frequency is (which needs to be determined somehow, possibly by measuring it with some other time source), in addition to avoiding various pitfalls (e.g. time stamp being different on different CPUs); and these things make it "not easy".

The other problem is that for a CPU running at several GHz each microsecond represents thousands of wasted clock cycles that the CPU could've spent doing useful work/running a different task, or even just doing nothing efficiently (by switching the CPU into a power saving state until a timer IRQ occurs). This is why a system call is better - the kernel is the only thing that has the privilege needed to implement time delays efficiently.

Brendan
  • 35,656
  • 2
  • 39
  • 66
  • you didn't provide any code :( – user1095108 Nov 05 '22 at 00:52
  • 1
    @user1095108: If you know the calibration of the TSC on your CPU (how many TSC ticks per microsecond), my answer on [How to calculate time for an asm delay loop on x86 linux?](https://stackoverflow.com/q/49924102) shows a spin-loop that uses that to calculate and do a simplistic spin wait for a TSC deadline. (Or use `tpause` if your CPU is new enough to support it.) It assumes that TSCs are synced across cores, or that this thread won't migrate during the spin (e.g. pinned to one core). Using `rdtscp` I could have checked the current core ID. – Peter Cordes Nov 05 '22 at 01:15
  • @PeterCordes I just miss the good old-fashioned asm routine listings. – user1095108 Nov 05 '22 at 07:05
  • 1
    @user1095108 Today's world is too complex for good old-fashioned asm routine listings. That's why answers like this are more valuable. Anyone knows how to turn a good approach into assembly code, the hard part is finding the good approach in the first place. – Margaret Bloom Nov 05 '22 at 11:08