Skip to content

Instantly share code, notes, and snippets.

@kisp
Last active November 25, 2022 01:22
Show Gist options
  • Save kisp/3bd6bc089f4dceb36e9f5db7830419e0 to your computer and use it in GitHub Desktop.
Save kisp/3bd6bc089f4dceb36e9f5db7830419e0 to your computer and use it in GitHub Desktop.
Setting real-time priority for a thread in sbcl

Setting real-time priority for a thread in sbcl

This is a small hack that shows how to set real-time priority for a thread in Common Lisp using sbcl by calling pthread_setschedparam(3). The code should be easily adaptable for other Common Lisp implementations.

The effect of doing so can be observed by calling ps(1) and chrt(1).

The cffi based code needed is in the file setschedparam.lisp. The file main.lisp serves as a demo.

Prerequisites

Running the demo

This demo shows the effect of calling (pthread-setschedparam :sched-rr 17) in a new thread created with sb-thread:make-thread.

$ { ./main.lisp & } ; sleep 1 ; ps ml $(cat sbcl.pid) ; chrt -ap $(cat sbcl.pid)
[1] 81145
To load "cffi":
  Load 1 ASDF system:
    cffi
; Loading "cffi"
............
hello
F   UID     PID    PPID PRI  NI    VSZ   RSS WCHAN  STAT TTY        TIME COMMAND
0  1000   81145   41968   -   - 1250512 113192 -    -    pts/5      0:00 sbcl --script ./main.li
0  1000       -       -  20   0      -     - futex_ Sl   -          0:00 -
1  1000       -       -  20   0      -     - futex_ Sl   -          0:00 -
1  1000       -       - -18   -      -     - hrtime Sl   -          0:00 -
pid 81145's current scheduling policy: SCHED_OTHER
pid 81145's current scheduling priority: 0
pid 81147's current scheduling policy: SCHED_OTHER
pid 81147's current scheduling priority: 0
pid 81150's current scheduling policy: SCHED_RR
pid 81150's current scheduling priority: 17
$ bye

[1]+  Done                    ./main.lisp
$
#!/bin/sh
#|-*- mode:lisp -*-|#
#|
exec sbcl --script "$0" "$@"
|#
(require 'sb-posix)
(load "~/quicklisp/setup.lisp")
(ql:quickload "cffi")
(with-open-file (out "sbcl.pid"
:direction :output
:if-exists :supersede)
(format out "~A~%" (sb-posix:getpid)))
(format t "hello~%")
(load "setschedparam.lisp")
(let ((thread
(sb-thread:make-thread
(lambda ()
(pthread-setschedparam :sched-rr 17)
(sleep 5)))))
(sb-thread:join-thread thread))
(format t "bye~%")
(in-package :cl-user)
(cffi:defcfun pthread-self :unsigned-long)
(cffi:defcfun (%pthread-setschedparam "pthread_setschedparam")
:int
(thread :unsigned-long)
(policy :int)
(sched-param :pointer))
(defun policy-code (policy)
(ecase policy
(:sched-other 0)
(:sched-fifo 1)
(:sched-rr 2)))
(defun pthread-setschedparam (policy sched-priority &key
(thread (pthread-self)))
(cffi:with-foreign-object (sched-param :int)
(setf (cffi:mem-ref sched-param :int)
sched-priority)
(ecase (%pthread-setschedparam
thread (policy-code policy) sched-param)
(0 t)
(#.sb-posix:einval
(error "pthread_setschedparam failed with EINVAL:~%~
Bad input arguments"))
(#.sb-posix:eperm
(error "pthread_setschedparam failed with EPERM:~%~
The caller does not have appropriate privileges~%~
to set the specified scheduling policy~%~
and parameters.")))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment