If there is any pausing/sleeping or events in x86 assembly
Asked Answered
B

2

5

I am wondering if there is anything at the assembly level in x86-64 that allows you to sleep/wait, such that no instructions are run until the wait is done. I have seen the WAIT and PAUSE instructions, but I'm not sure they're related.

I would imagine it like this:

start:
  wait 123, oninterrupt ; 123 milliseconds
  ; then it will go here after that time
oninterrupt:
  ; ctrl-c pressed, now exit

Likewise, I am wondering if there are event hooks/handlers in x86. So if someone presses CTRL+C, there will be an interrupt event sent to assembly somewhere and you can run your "exit" code on that. I would imagine an event handler could be written in assembly x86 like this:

start:
  int 10, onctrlc ; register handler for made up event
  ; ... more instructions evaluate right after
onctrlc:
  ; control+c pressed, now exit

But I'm not just thinking for CTRL+C, but for any event (which I don't know that much about). I saw this tiny event loop lib in C, not sure if any of that can be done with a simple assembly instruction. Things like keyboard events, socket events, file events, other events I'm not sure what they would be.

Also, this would be run as a regular user on an operating system. But knowing how to do it for privileged users would be nice to know. And also not concerned with how you can do it with linux C functions or syscalls, I understand how to do it like that so far.

Boracite answered 22/3, 2019 at 8:33 Comment(1)
That C will compile to asm that makes system calls (via wrapper functions in libc, but you could inline them if you want). If your code is supposed to run under an OS, "sleeping" is an interaction with the process scheduler / OS, not the CPU hardware directly. \@fuz's answer is what you really want here, although \@prl's answer does correctly answer the literal question you asked based on your XY problem.Litha
M
11

The basic instruction to do what you want is HALT. It stops executing instructions until an interrupt is received.

A newer instruction that is similar is MWAIT. It waits like halt, but it also wakes up when a particular memory location is written (either by a different CPU core or by an I/O device). MWAIT also puts the CPU in a lower power state than halt does. The MONITOR instruction is used to specify the memory location that will cause MWAIT to wake up.

The other types of events you mentioned are software constructs. The CPU instructions don’t know about keyboards, files, or network devices.

MWAIT and HALT are privileged instructions. If an application wants to put the CPU to sleep, it generally needs to call the OS, so the OS can schedule some other process, if there is one ready to run.

Myelencephalon answered 22/3, 2019 at 8:48 Comment(2)
Fun fact: The WAITPKG CPU feature will add a timed-pause tpause until a given TSC count, and umonitor / umwait to monitor/mwait from user-space (hyperthreading-friendly alternative to spin-wait I guess, but presumably deep sleep like mwait isn't an option). I think these are only slated for Tremont (next-gen goldmont low-power) en.wikichip.org/wiki/intel/microarchitectures/…Litha
Looking for a WIN32 solution - Vis Studio, Borland, everyone's Sleep() seems to be a black box. I've tried HALT and MWAIT -- they tend to kill my entire process, but maybe I'm doing it wrong. C mixed with assembly like thisYaekoyael
T
3

While there are instructions to do this, they are not useful for a process running under an operating system as you are not allowed to use them. Neither do you have a way to make use of interrupts. Instead, use system calls and signals to achieve the desired goal. Useful system calls are:

  • nanosleep stops your process for the specified number of nanoseconds.
  • sigaction and signal configure what happens when a signal is received.
  • pause suspends the process until a signal is received.

On UNIX-like systems such as Linux, a SIGINT is delivered to your process when the user presses Ctrl + C. This behaviour can be used to achieve the desired result.

I recommend you to first practice all these concepts in C before diving into an assembly implementation.

Teakwood answered 22/3, 2019 at 13:4 Comment(3)
I'am very surprised. You say it stops / suspends a process? The CPU has no idea about processes. I suppose you want to say it stops / suspends a thread?Vambrace
@Vambrace The CPU has no idea about threads either. This question is not about threads and I do not want to complicate my answer by diving into the details of multi-threading. Note that while the methods I gave work on threads technically, it is indeed possible to susped the whole process for a given time.Teakwood
@Elmue: This answer is talking about the POSIX pause() function / system-call (man7.org/linux/man-pages/man2/pause.2.html), not the x86 pause instruction (felixcloutier.com/x86/pause) which pauses the front-end for about 5 or 100 cycles (Skylake and later) and hints the CPU to avoid memory-order mis-speculation.Litha

© 2022 - 2024 — McMap. All rights reserved.