8

ドキュメントのgetErrno読み取り:

現在のスレッドの errno の現在の値を取得します。

これが現在のOSスレッドを意味するかどうかは不明です。errno特に、(スレッド化された) ランタイムは、Haskell スレッドがある OS スレッドから別の OS スレッドに移行されるたびに、フェッチして隠しておきますか?

この質問は関連しているようですが、そこで言われていることがOSまたはHaskellスレッドに関係するかどうかは不明です。

4

1 に答える 1

7

少なくとも最近のバージョンの GHC では、ランタイムerrnoはスレッド ストレージ オブジェクト ( TSO) に保存し、ランタイム スレッドを別の OS スレッドに移行するときにそれを管理します。つまり、バインドされていない ( ) スレッドとバインドされている ( ) スレッドerrnoの両方で安全に依存できる必要があります。Linux のテストは次のとおりです。forkIOforkOS

err.hs

import Control.Concurrent
import Control.Exception
import Foreign.C

foreign import ccall safe get_ostid :: IO CUInt
foreign import ccall safe sleep :: CUInt -> IO CUInt
foreign import ccall unsafe get_errno :: IO CInt
foreign import ccall unsafe set_errno :: CInt -> IO ()

forkIO' f = do
  done <- newEmptyMVar
  forkIO (f `finally` putMVar done ())
  return (takeMVar done)

prefix = do
  id <- get_ostid
  return $ show id ++ ": "

main = do
  wait <- forkIO' $ do -- spawn a lightweight thread
    errno <- get_errno
    (putStr =<< prefix) >> putStrLn ("outer errno is " ++ show errno)
    (putStr =<< prefix) >> putStrLn "Setting outer errno to 3"
    set_errno 3
    wait' <- forkIO' $ do -- spawn another lightweight thread
      errno <- get_errno
      (putStr =<< prefix) >> putStrLn ("inner errno is " ++ show errno)
      (putStr =<< prefix) >> putStrLn "Setting inner errno to 2"
      set_errno 2
      sleep 2 -- force this lightweight thread to tie up the OS thread
      errno <- get_errno
      (putStr =<< prefix) >> putStrLn ("inner errno is " ++ show errno)
    threadDelay 1000000 -- wait a second
    -- By now, we should be in another OS thread.
    errno <- get_errno
    (putStr =<< prefix) >> putStrLn ("outer errno is " ++ show errno)
    wait'
  wait

err.c

#include <errno.h>
#include <sys/syscall.h>
#include <unistd.h>

int get_errno(void) { return errno; }
void set_errno(int e) { errno = e; }

unsigned get_ostid(void) {
  return syscall(SYS_gettid);
}

コンパイル:

ghc -o err -threaded err.hs err.c

結果は次のようになります。

12282: outer errno is 0
12282: Setting outer errno to 3
12282: inner errno is 0
12282: Setting inner errno to 2
12283: outer errno is 3
12282: inner errno is 2

OS スレッド ID は、各行の先頭に出力されます。が 2 番目の OS スレッドに移行されたことerrnoに注意してください( )。312283

于 2013-01-27T23:22:45.070 に答える