Submit Search
Upload
ttwrite
•
0 likes
•
1,031 views
K
kusabanachi
Follow
NetBSD-6.0.1のソースコードリーディング.
Read less
Read more
Technology
Slideshow view
Report
Share
Slideshow view
Report
Share
1 of 45
Download now
Download to read offline
Recommended
dofilewrite and vn_write
dofilewrite and vn_write
kusabanachi
NetBSD-6.0.1のコードリーディング。
cdev_write and_comwrite
cdev_write and_comwrite
kusabanachi
NetBSD-6.0.1のソースコードリーディング。
php-src の歩き方
php-src の歩き方
do_aki
PHP カンファレンス福岡 リジェクトコン で発表した資料
PHP AST 徹底解説
PHP AST 徹底解説
do_aki
phpカンファレンス2016
SSE4.2の文字列処理命令の紹介
SSE4.2の文字列処理命令の紹介
MITSUNARI Shigeo
intorduction of SSE4.2 string instructions
Async design with Unity3D
Async design with Unity3D
Kouji Hosoda
UnityでHTTP通信をするときに割りと困りがちな非同期処理の設計についてロードオブナイツで使っているデザインを公開します。スライド作成は++c++;の中の人。
Cvim saisentan 半精度浮動小数点数 half
Cvim saisentan 半精度浮動小数点数 half
tomoaki0705
CV勉強会の資料 http://kantocv.connpass.com/event/27432/ https://sites.google.com/site/cvsaisentan/
Kanazawa.js.Next
Kanazawa.js.Next
dynamis
Kanazawa.js 1.7 with Mozilla で利用したスライド 容量 10MB 制限があった時期に SpeakerDeck に UP していたもの: http://speakerdeck.com/u/dynamis/p/kanazawajavascriptnext
Recommended
dofilewrite and vn_write
dofilewrite and vn_write
kusabanachi
NetBSD-6.0.1のコードリーディング。
cdev_write and_comwrite
cdev_write and_comwrite
kusabanachi
NetBSD-6.0.1のソースコードリーディング。
php-src の歩き方
php-src の歩き方
do_aki
PHP カンファレンス福岡 リジェクトコン で発表した資料
PHP AST 徹底解説
PHP AST 徹底解説
do_aki
phpカンファレンス2016
SSE4.2の文字列処理命令の紹介
SSE4.2の文字列処理命令の紹介
MITSUNARI Shigeo
intorduction of SSE4.2 string instructions
Async design with Unity3D
Async design with Unity3D
Kouji Hosoda
UnityでHTTP通信をするときに割りと困りがちな非同期処理の設計についてロードオブナイツで使っているデザインを公開します。スライド作成は++c++;の中の人。
Cvim saisentan 半精度浮動小数点数 half
Cvim saisentan 半精度浮動小数点数 half
tomoaki0705
CV勉強会の資料 http://kantocv.connpass.com/event/27432/ https://sites.google.com/site/cvsaisentan/
Kanazawa.js.Next
Kanazawa.js.Next
dynamis
Kanazawa.js 1.7 with Mozilla で利用したスライド 容量 10MB 制限があった時期に SpeakerDeck に UP していたもの: http://speakerdeck.com/u/dynamis/p/kanazawajavascriptnext
コルーチンの使い方
コルーチンの使い方
Naohiro Yoshikawa
ゲームのモデルに存在する流れの記述をコルーチンで直感的に書いていきましょう。
llvm入門
llvm入門
MITSUNARI Shigeo
effective modern c++ chapeter36
effective modern c++ chapeter36
Tatsuki SHIMIZU
effective modern c++ chapeter36
Continuation with Boost.Context
Continuation with Boost.Context
Akira Takahashi
Effective modern-c++#9
Effective modern-c++#9
Tatsuki SHIMIZU
effective modern c++ 勉強会(tmpral update)
Boost.Coroutine
Boost.Coroutine
melpon
emc++ chapter32
emc++ chapter32
Tatsuki SHIMIZU
Effective Modern C++ 勉強会 #7 chapter32 発表用スライド
trueコマンドに0以外の終了コードをはかせる方法
trueコマンドに0以外の終了コードをはかせる方法
mutz0623
第19回シェル芸勉強会でLTしました
Sharing Deep Dive
Sharing Deep Dive
Takaaki Suzuki
30 分で掴み取る HoloLens で最もクールな機能の勘所
Scalaの限定継続の応用と基本
Scalaの限定継続の応用と基本
Kota Mizushima
Scalaの限定継続の応用と基本を高橋メソッド風味で説明したプレゼンです。
Swift 2.0 の Error Handling #yhios
Swift 2.0 の Error Handling #yhios
Tomohiro Kumagai
Swift 2.0 で新登場した Error Handling についての特徴や使い方などを、これまでの Swift 1.x にもあったその他のエラー処理の方法と合わせて紹介してみました。
Effective Modern C++ 読書会 Item 35
Effective Modern C++ 読書会 Item 35
Keisuke Fukuda
発表資料です
What is Metasepi?
What is Metasepi?
Kiwamu Okabe
http://metasepi.masterq.net/
Visual C++コード分析を支えるSAL
Visual C++コード分析を支えるSAL
egtra
Boost.勉強会 #21 札幌の発表時のスライドです。Visual C++のコード分析機能で使われるSALの導入的な説明です。
Php in ruby
Php in ruby
do_aki
Inside winnyp
Inside winnyp
FFRI, Inc.
Inside FastEnum
Inside FastEnum
Takaaki Suzuki
Event : .NET Conf in Tokyo 2019 Date : 2019/10/27 .NET Core 3.0 がリリースされさらなるパフォーマンスチューニングが行われましたが、Enum は依然として遅いままです。FastEnum はその苦痛を緩和する世界最速の Enum Utility ライブラリです。 このドキュメントでは FastEnum の中で使われているテクニックや .NET Core 標準が遅い理由などについて解説し、速いコードを書くための一助となるようにします。
20分くらいでわかった気分になれるC++20コルーチン
20分くらいでわかった気分になれるC++20コルーチン
yohhoy
C++MIX #5 資料
ジェネリック関数の呼び出され方 #cocoa_kansai
ジェネリック関数の呼び出され方 #cocoa_kansai
Tomohiro Kumagai
Swift 2.0 で登場した目玉機能の『Protocol Extension』はジェネリックという型にとらわれない仕組みを活かしたものになっています。 ジェネリックでは様々な型をプロトコルなどの様々な条件を組み合わせて機能実装を行っていくんですが、条件によっては、どれが該当するのか、どれが優先されるのか、そもそもビルドエラーになるのか。基本的にはシンプルなルールを組み合わせて作れば良さそうですが、実際にやってみると結構混乱します。 その辺りをサクッと体系立てて紹介できれば…と思ったんですが、調べてみれば微妙な違いがたくさんあって、そこまでたどり着けませんでした。 続きはぜひぜひ、みなさんの目で確かめてみてください。
CS集会#13_なるほどわからん通信技術 発表資料
CS集会#13_なるほどわからん通信技術 発表資料
Yuuitirou528 default
CS集会でお話した、通信技術のひとつである「変調」について解説した資料です。 https://x.com/vrc_cpu_science/status/1724784316738355560
ReonHata_便利の副作用に気づかせるための発想支援手法の評価---行為の増減の提示による気づきへの影響---
ReonHata_便利の副作用に気づかせるための発想支援手法の評価---行為の増減の提示による気づきへの影響---
Matsushita Laboratory
我々はこれまで,新たなモノを産出する過程において「便利にすること」によって副次的に生じる課題を「便利の副作用」と定義し,その低減を目的としてアイディアの発想支援手法を提案してきた. これまでの研究では,便利前後の行為の増減に着目することにより便利の副作用への気づきの誘発が示唆されたものの,行為の増減の提示による便利の副作用への気づきへの影響は十分に検討できていなかった. そのため,本稿では行為の提示により便利の副作用に気づき,それを防いだアイディアの発想の支援が可能かの検証を目的として実験を行い,その有効性について検証する. 実験では,行為の増減の提示の有無によりアイディア発想にどのような影響を与えるか検証を行う.
TaketoFujikawa_物語のコンセプトに基づく情報アクセス手法の基礎検討_JSAI2024
TaketoFujikawa_物語のコンセプトに基づく情報アクセス手法の基礎検討_JSAI2024
Matsushita Laboratory
浜松で開催されたJSAI2024(第38回)での発表.
More Related Content
What's hot
コルーチンの使い方
コルーチンの使い方
Naohiro Yoshikawa
ゲームのモデルに存在する流れの記述をコルーチンで直感的に書いていきましょう。
llvm入門
llvm入門
MITSUNARI Shigeo
effective modern c++ chapeter36
effective modern c++ chapeter36
Tatsuki SHIMIZU
effective modern c++ chapeter36
Continuation with Boost.Context
Continuation with Boost.Context
Akira Takahashi
Effective modern-c++#9
Effective modern-c++#9
Tatsuki SHIMIZU
effective modern c++ 勉強会(tmpral update)
Boost.Coroutine
Boost.Coroutine
melpon
emc++ chapter32
emc++ chapter32
Tatsuki SHIMIZU
Effective Modern C++ 勉強会 #7 chapter32 発表用スライド
trueコマンドに0以外の終了コードをはかせる方法
trueコマンドに0以外の終了コードをはかせる方法
mutz0623
第19回シェル芸勉強会でLTしました
Sharing Deep Dive
Sharing Deep Dive
Takaaki Suzuki
30 分で掴み取る HoloLens で最もクールな機能の勘所
Scalaの限定継続の応用と基本
Scalaの限定継続の応用と基本
Kota Mizushima
Scalaの限定継続の応用と基本を高橋メソッド風味で説明したプレゼンです。
Swift 2.0 の Error Handling #yhios
Swift 2.0 の Error Handling #yhios
Tomohiro Kumagai
Swift 2.0 で新登場した Error Handling についての特徴や使い方などを、これまでの Swift 1.x にもあったその他のエラー処理の方法と合わせて紹介してみました。
Effective Modern C++ 読書会 Item 35
Effective Modern C++ 読書会 Item 35
Keisuke Fukuda
発表資料です
What is Metasepi?
What is Metasepi?
Kiwamu Okabe
http://metasepi.masterq.net/
Visual C++コード分析を支えるSAL
Visual C++コード分析を支えるSAL
egtra
Boost.勉強会 #21 札幌の発表時のスライドです。Visual C++のコード分析機能で使われるSALの導入的な説明です。
Php in ruby
Php in ruby
do_aki
Inside winnyp
Inside winnyp
FFRI, Inc.
Inside FastEnum
Inside FastEnum
Takaaki Suzuki
Event : .NET Conf in Tokyo 2019 Date : 2019/10/27 .NET Core 3.0 がリリースされさらなるパフォーマンスチューニングが行われましたが、Enum は依然として遅いままです。FastEnum はその苦痛を緩和する世界最速の Enum Utility ライブラリです。 このドキュメントでは FastEnum の中で使われているテクニックや .NET Core 標準が遅い理由などについて解説し、速いコードを書くための一助となるようにします。
20分くらいでわかった気分になれるC++20コルーチン
20分くらいでわかった気分になれるC++20コルーチン
yohhoy
C++MIX #5 資料
ジェネリック関数の呼び出され方 #cocoa_kansai
ジェネリック関数の呼び出され方 #cocoa_kansai
Tomohiro Kumagai
Swift 2.0 で登場した目玉機能の『Protocol Extension』はジェネリックという型にとらわれない仕組みを活かしたものになっています。 ジェネリックでは様々な型をプロトコルなどの様々な条件を組み合わせて機能実装を行っていくんですが、条件によっては、どれが該当するのか、どれが優先されるのか、そもそもビルドエラーになるのか。基本的にはシンプルなルールを組み合わせて作れば良さそうですが、実際にやってみると結構混乱します。 その辺りをサクッと体系立てて紹介できれば…と思ったんですが、調べてみれば微妙な違いがたくさんあって、そこまでたどり着けませんでした。 続きはぜひぜひ、みなさんの目で確かめてみてください。
What's hot
(19)
コルーチンの使い方
コルーチンの使い方
llvm入門
llvm入門
effective modern c++ chapeter36
effective modern c++ chapeter36
Continuation with Boost.Context
Continuation with Boost.Context
Effective modern-c++#9
Effective modern-c++#9
Boost.Coroutine
Boost.Coroutine
emc++ chapter32
emc++ chapter32
trueコマンドに0以外の終了コードをはかせる方法
trueコマンドに0以外の終了コードをはかせる方法
Sharing Deep Dive
Sharing Deep Dive
Scalaの限定継続の応用と基本
Scalaの限定継続の応用と基本
Swift 2.0 の Error Handling #yhios
Swift 2.0 の Error Handling #yhios
Effective Modern C++ 読書会 Item 35
Effective Modern C++ 読書会 Item 35
What is Metasepi?
What is Metasepi?
Visual C++コード分析を支えるSAL
Visual C++コード分析を支えるSAL
Php in ruby
Php in ruby
Inside winnyp
Inside winnyp
Inside FastEnum
Inside FastEnum
20分くらいでわかった気分になれるC++20コルーチン
20分くらいでわかった気分になれるC++20コルーチン
ジェネリック関数の呼び出され方 #cocoa_kansai
ジェネリック関数の呼び出され方 #cocoa_kansai
Recently uploaded
CS集会#13_なるほどわからん通信技術 発表資料
CS集会#13_なるほどわからん通信技術 発表資料
Yuuitirou528 default
CS集会でお話した、通信技術のひとつである「変調」について解説した資料です。 https://x.com/vrc_cpu_science/status/1724784316738355560
ReonHata_便利の副作用に気づかせるための発想支援手法の評価---行為の増減の提示による気づきへの影響---
ReonHata_便利の副作用に気づかせるための発想支援手法の評価---行為の増減の提示による気づきへの影響---
Matsushita Laboratory
我々はこれまで,新たなモノを産出する過程において「便利にすること」によって副次的に生じる課題を「便利の副作用」と定義し,その低減を目的としてアイディアの発想支援手法を提案してきた. これまでの研究では,便利前後の行為の増減に着目することにより便利の副作用への気づきの誘発が示唆されたものの,行為の増減の提示による便利の副作用への気づきへの影響は十分に検討できていなかった. そのため,本稿では行為の提示により便利の副作用に気づき,それを防いだアイディアの発想の支援が可能かの検証を目的として実験を行い,その有効性について検証する. 実験では,行為の増減の提示の有無によりアイディア発想にどのような影響を与えるか検証を行う.
TaketoFujikawa_物語のコンセプトに基づく情報アクセス手法の基礎検討_JSAI2024
TaketoFujikawa_物語のコンセプトに基づく情報アクセス手法の基礎検討_JSAI2024
Matsushita Laboratory
浜松で開催されたJSAI2024(第38回)での発表.
JSAI_類似画像マッチングによる器への印象付与手法の妥当性検証_ver.3_高橋りさ
JSAI_類似画像マッチングによる器への印象付与手法の妥当性検証_ver.3_高橋りさ
0207sukipio
JSAI2024の発表スライドです.
論文紹介:When Visual Prompt Tuning Meets Source-Free Domain Adaptive Semantic Seg...
論文紹介:When Visual Prompt Tuning Meets Source-Free Domain Adaptive Semantic Seg...
Toru Tamaki
Xinhong Ma, Yiming Wang, Hao Liu, Tianyu Guo, Yunhe Wang, "When Visual Prompt Tuning Meets Source-Free Domain Adaptive Semantic Segmentation" NeurIPS2023 https://proceedings.neurips.cc/paper_files/paper/2023/hash/157c30da6a988e1cbef2095f7b9521db-Abstract-Conference.html
LoRaWAN 4チャンネル電流センサー・コンバーター CS01-LB 日本語マニュアル
LoRaWAN 4チャンネル電流センサー・コンバーター CS01-LB 日本語マニュアル
CRI Japan, Inc.
LoRaWAN 4チャンネル電流センサー・コンバーター CS01-LB 日本語マニュアル
遺伝的アルゴリズムと知識蒸留による大規模言語モデル(LLM)の学習とハイパーパラメータ最適化
遺伝的アルゴリズムと知識蒸留による大規模言語モデル(LLM)の学習とハイパーパラメータ最適化
t m
オープンエンドな進化から着想を得て、個々の大規模言語モデル(LLM)が、グループとして学習を進めながら、ノームエージェントとして機能するという概念を探求しています。これは、単一のモデルでは難しい複雑な問題を解決することを目的としています。具体的な方法として、遺伝的アルゴリズムと知識蒸留を組み合わせた学習プロセスを提案しています。知識蒸留によって学習を進め、同時に遺伝的アルゴリズムでハイパーパラメータを最適化することで、より効率的な学習を目指します。ドメインタスクとして、指示からPythonコードを生成するコード生成タスクを選択しました。実験では、学習に3つの学習モデルと1つの教師モデルを使用しました。その結果、HumanEvalのpass@1で精度が1.2%向上し、学習が進むにつれて学習率が最適化された兆候が見られました。しかし、大幅な精度向上を達成し、さまざまなハイパーパラメータを最適化するには、まだ課題が残っています。
This is the company presentation material of RIZAP Technologies, Inc.
This is the company presentation material of RIZAP Technologies, Inc.
chiefujita1
RIZAPテクノロジーズ株式会社の会社説明資料です。
Recently uploaded
(8)
CS集会#13_なるほどわからん通信技術 発表資料
CS集会#13_なるほどわからん通信技術 発表資料
ReonHata_便利の副作用に気づかせるための発想支援手法の評価---行為の増減の提示による気づきへの影響---
ReonHata_便利の副作用に気づかせるための発想支援手法の評価---行為の増減の提示による気づきへの影響---
TaketoFujikawa_物語のコンセプトに基づく情報アクセス手法の基礎検討_JSAI2024
TaketoFujikawa_物語のコンセプトに基づく情報アクセス手法の基礎検討_JSAI2024
JSAI_類似画像マッチングによる器への印象付与手法の妥当性検証_ver.3_高橋りさ
JSAI_類似画像マッチングによる器への印象付与手法の妥当性検証_ver.3_高橋りさ
論文紹介:When Visual Prompt Tuning Meets Source-Free Domain Adaptive Semantic Seg...
論文紹介:When Visual Prompt Tuning Meets Source-Free Domain Adaptive Semantic Seg...
LoRaWAN 4チャンネル電流センサー・コンバーター CS01-LB 日本語マニュアル
LoRaWAN 4チャンネル電流センサー・コンバーター CS01-LB 日本語マニュアル
遺伝的アルゴリズムと知識蒸留による大規模言語モデル(LLM)の学習とハイパーパラメータ最適化
遺伝的アルゴリズムと知識蒸留による大規模言語モデル(LLM)の学習とハイパーパラメータ最適化
This is the company presentation material of RIZAP Technologies, Inc.
This is the company presentation material of RIZAP Technologies, Inc.
ttwrite
1.
ttwrite() スタート低レイヤー #6 #start_printf @kusabanachi
2.
ttwrite() 全体像
3.
ttwrite() 引数 int ttwrite(struct tty *tp, struct uio *uio, int flag) tp: 対象の端末、出力先 uio: writeするデータのアドレス、サイズなど flag: writeに関するフラグ (追記、ブロック無し、同期、バッファリング無しなど)
4.
接続が無い場合の処理
5.
接続が無い場合の処理 loop: mutex_spin_enter(&tty_lock); if (!CONNECTED(tp)) { if (ISSET(tp>t_state, TS_ISOPEN)) { mutex_spin_exit(&tty_lock); return (EIO); } else if (flag & IO_NDELAY) { mutex_spin_exit(&tty_lock); error = EWOULDBLOCK; goto out; } else { /* Sleep awaiting carrier. */ error = ttysleep(tp, &tp>t_rawcv, true, 0); mutex_spin_exit(&tty_lock); if (error) goto out; goto loop; } }
6.
接続が無い場合の処理 TERMIOS(4) (全般的な端末の回線規則) より 端末デバイスファイルのオープン 端末ファイルがオープンされると、プロセスは通信の確立を待つ ほとんどのハードウェアではCARRIERDETECT(CD)線で接続が分かる
7.
接続が無い場合の処理 CONNECTED() /* * まだ接続しているか判断するために使われる. いずれかの場合にtrueになる * 1) キャリアを持っている * 2) ローカルにアタッチされた端末なので、キャリアを無視する * 3) キャリア信号をオーバーロードするフロー制御機構を使っている */ #define CONNECTED(tp) (ISSET(tp>t_state, TS_CARR_ON) || ISSET(tp>t_cflag, CLOCAL | MDMBUF)) #define ISSET(t, f) ((t) & (f)) #define TS_CARR_ON 0x00008 /* キャリアがある. */ < 1)のケース #define CLOCAL 0x00008000 /* モデムの状態線を無視する. */ < 2) #define MDMBUF 0x00100000 /* DTR/DCD hardwareフロー制御 */ < 3)
8.
接続が無い場合の処理 if (!CONNECTED(tp)) { if (ISSET(tp>t_state, TS_ISOPEN)) { mutex_spin_exit(&tty_lock); return (EIO); } else if (... #define TS_ISOPEN 0x00040 /* Openが完了している. */ #define EIO 5 /* 入出力エラー */ 接続していないのに、オープン済みの場合はEIOのエラーで戻る
9.
接続が無い場合の処理 if (!CONNECTED(tp)) { ... } else if (flag & IO_NDELAY) { mutex_spin_exit(&tty_lock); error = EWOULDBLOCK; goto out; } else ... #define IO_NDELAY 0x00100 /* FNDELAYがファイルテーブルでセットされた */ #define FNDELAY O_NONBLOCK /* compat(互換用) */ #define O_NONBLOCK 0x00000004 /* no delay */ #define EWOULDBLOCK EAGAIN /* 処理はブロックする */ 接続していなくて、ディレイ無し指定のwriteの場合は、 (接続を待つ必要があるため) EWOULDBLOCKのエラーでoutラベル(終了処理)へ。
10.
接続が無い場合の処理 loop: mutex_spin_enter(&tty_lock); if (!CONNECTED(tp)) { ... } else { /* キャリアを待ってsleepする. */ error = ttysleep(tp, &tp>t_rawcv, true, 0); mutex_spin_exit(&tty_lock); if (error) goto out; goto loop; } } ttysleepでキャリアの検出を待つ --> errorであった場合は、終了処理へ飛ぶ。 --> errorが無ければ、最初に戻って接続状態を調べる struct tty { ... kcondvar_t t_rawcv; /* 通知 */
11.
接続が無い場合の処理 /* * チャンネル上でsleepし、寝ている間にttyが変化した場合はERESTARTを返す。また、 * cv_timedwait(_sig)で報告されたエラーのいずれか(EINTR/EWOULDBLOCK)を返す。 * ttyが取り消された場合は、保留中の呼び出しを再開すると、 * 呼び出しの開始時に行われた検証をやり直す。 * * tty lockを保持した状態で、呼び出すこと */ int ttysleep(struct tty *tp, kcondvar_t *cv, bool catch, int timo) { int error; short gen; KASSERT(mutex_owned(&tty_lock)); /// < tty lockを保持していること gen = tp>t_gen; /// < 寝る前の世代を取得しておく ... ... /// < sleep処理 ... return (tp>t_gen == gen ? 0 : ERESTART); /// < 世代が変わっていたら、ERESTART }
12.
接続が無い場合の処理 int ttysleep(struct tty *tp, kcondvar_t *cv, bool catch, int timo) { ... gen = tp>t_gen; if (cv == NULL) error = kpause("ttypause", catch, timo, &tty_lock); /// condition variableがNULLの場合はkpauseで待つ else if (catch) error = cv_timedwait_sig(cv, &tty_lock, timo); /// catchがtrueの場合、signal付きのwait else error = cv_timedwait(cv, &tty_lock, timo); /// catchがfalseの場合、signal無しのwait if (error != 0) return (error); /// エラーがあればエラーで戻る return (tp>t_gen == gen ? 0 : ERESTART); /// エラー無しでttyも変わってなければ、0で戻る }
13.
CONDVAR(9) より ConditionVariables(CVs)はカーネル内でリソースへのアクセスを 同期するため、I/O操作の完了を待つために使われる。 kcondvar_t型はCVオブジェクトのストレージを提供する。 不透明なオブジェクトとして扱い、使用者に直接検査されるべきでない。
14.
CONDVAR(9) より cv_wait(cv, mtx) LWPに割り込み不可なwaitをさせる。 LWPは他のスレッドのcv_signal()またはcv_broadcast()で実行再開する。 cv_wait()に入る時にmutexを持っていなければならない。 LWPがsleepの準備をした時点でmutexはリリースされ、cv_wait()から戻る前 に再取得される。 リソースが利用可能かのテストとcv_wait()でリソースを待つ間に、 リソースが利用可能にならないことをmutexは保証する。 割り込み不可のwaitはシステムをデッドロックする可能性があるので、 短い間(通常は、1秒未満)にしなければならない
15.
CONDVAR(9) より cv_wait_sig(cv, mtx) cv_wait()と同様だが、LWPに割り込み可能なwaitをさせる。 signalの受信、またはLWPを含むプロセスの終了のようなの割り込みで waitは早期に終了し、エラーコードを返す。 cv_timedwait(cv, mtx,
ticks) cv_wait()と同様だが、ticks引数で指定されたタイムアウト付き ticksは秒間のクロック割り込みの数に関連する、アーキテクチャとシステ ム依存値。 ticksがゼロの場合、cv_timedwait()はcv_wait()のように動作する。 cv_timedwait_sig(cv, mtx, ticks) cv_wait_sig()と同様だが、タイムアウト付き
16.
KPAUSE(9) より kpause(const char *wmesg,
bool intr, int timo, kmutex_t *mtx) LWPをsleepさせる。 対応するcv_signal(9)の無いcv_timedwait_sig(9)に似ている。 kpause()は自分で起きる可能性があるので、 呼び出し元は対処しなければならない。 wmesg: kpause()に関連するリソースや条件を表す文字列 intr: trueなら、シグナル / 割り込み可能にsleepする timeo: タイムアウト mtx: mutex
17.
接続が無い場合の処理 /* キャリアを待ってsleepする. */ error = ttysleep(tp, &tp>t_rawcv, true, 0); int ttysleep(struct tty *tp, kcondvar_t *cv, bool catch, int timo) { ... gen = tp>t_gen; if (cv == NULL) error = kpause("ttypause", catch, timo, &tty_lock); /// condition variableがNULLの場合はkpauseで待つ else if (catch) error = cv_timedwait_sig(cv, &tty_lock, timo); /// catchがtrueの場合、signal付きのwait else error = cv_timedwait(cv, &tty_lock, timo); /// catchがfalseの場合、signal無しのwait ... ttwrite()からは Condition Variable有り、割り込み可能、タイムアウト無しで cv_timedwait_sig(&tp->t_rawcv, &tty_lock,
0) が呼ばれるだろう
18.
接続が無い場合の処理 まとめ loop: mutex_spin_enter(&tty_lock); if (!CONNECTED(tp)) { /// 接続しているかチェック if (ISSET(tp>t_state, TS_ISOPEN)) { mutex_spin_exit(&tty_lock); return (EIO); /// オープン済みはエラー } else if (flag & IO_NDELAY) { mutex_spin_exit(&tty_lock); error = EWOULDBLOCK; goto out; /// ディレイ無し指定はエラー } else { /* キャリアを待ってsleepする. */ error = ttysleep(tp, &tp>t_rawcv, true, 0); mutex_spin_exit(&tty_lock); if (error) goto out; /// sleepの間にエラー goto loop; /// エラー0の場合、最初からリスタート } }
19.
バックグラウンドの場合の処理
20.
バックグラウンドの場合の処理 /* * プロセスがバックグラウンドの場合、ハングアップさせる */ p = curproc; if (isbackground(p, tp) && ISSET(tp>t_lflag, TOSTOP) && (p>p_lflag & PL_PPWAIT) == 0 && !sigismasked(curlwp, SIGTTOU)) { if (p>p_pgrp>pg_jobc == 0) { error = EIO; mutex_spin_exit(&tty_lock); goto out; } mutex_spin_exit(&tty_lock); mutex_enter(proc_lock); pgsignal(p>p_pgrp, SIGTTOU, 1); mutex_exit(proc_lock); mutex_spin_enter(&tty_lock); error = ttypause(tp, hz); mutex_spin_exit(&tty_lock); if (error) goto out; goto loop; } mutex_spin_exit(&tty_lock);
21.
TERMIOS(4) より Session PGID xxx0 (bg) login PGID xxx2 (bg) emacs PGID xxx3 (bg) emacs PGID xxx4 (fg) ps PGID xxx1 (bg) tail grep pipe tty foreground ログインシェルから生成されたプロセスは同じセッション 関連するプロセスは同じプロセスグループに置かれる 端末にはフォアグラウンドのプロセスグループIDが割り当てられている 特殊なケースを除いて、フォアグラウンドのプロセスグループだけが端 末のread/writeを許可される
22.
TERMIOS(4) より 孤児になるプロセスグループ 同じセッション内で違うプロセスグループに親がいる、 というプロセスが1つもない 概念的に、プロセスグループ終了時に世話してくれる親がいない意味 キーボードからのストップシグナルやジョブ制御シグナルの影響を受け ない
23.
孤児になるプロセスグループ 同じセッション内で違うプロセスグループに親がいる、 というプロセスが1つもない
24.
バックグラウンドの場合の処理 /* 端末tpはプロセスpの制御端末か? */ #define isctty(p, tp) ((p)>p_session == (tp)>t_session && (p)>p_lflag & PL_CONTROLT) /// pとtpのセッションが同じ && pは制御端末を持つ /* プロセスpは端末tpのバックグラウンドか? */ #define isbackground(p, tp) (isctty((p), (tp)) && (p)>p_pgrp != (tp)>t_pgrp) /// tpがpの制御端末 && /// pのプロセスグループがtのフォアグラウンド プロセスグループではない struct tty { ... struct pgrp *t_pgrp; /* フォアグラウンド プロセスグループ */ #define PL_CONTROLT 0x00000002 /* 制御端末を持つ */
25.
バックグラウンドの場合の処理 p = curproc; if (isbackground(p, tp) && ISSET(tp>t_lflag, TOSTOP) && (p>p_lflag & PL_PPWAIT) == 0 && !sigismasked(curlwp, SIGTTOU)) { /// pはバックグラウンド プロセスグループ && /// TOSTOPがセットされている && 親が子のexec/exitを待っていない && /// SIGTTOUシグナルをマスクしていない TERMIOS(4) より 端末のアクセスコントロール バックグラウンド プロセスグループのプロセスから制御端末へのwriteは 以下の特殊ケース以外はSIGTTOUシグナルが送信される TOSTOPがセットされていない プロセスがSIGTTOUシグナルを無視かブロックしている writeするプロセスのプロセスグループが孤児の場合、 write(2)はEIOのerrnoと供に-1を返してシグナルは送信されない #define PL_PPWAIT 0x00000010 /* 親は子のexec/exitを待っている */
26.
バックグラウンドの場合の処理 p = curproc; if (isbackground(p, tp) && ISSET(tp>t_lflag, TOSTOP) && (p>p_lflag & PL_PPWAIT) == 0 && !sigismasked(curlwp, SIGTTOU)) { if (p>p_pgrp>pg_jobc == 0) { ... } ... struct pgrp { ... int pg_jobc; /* プロセスグループをジョブ制御の<br> 適任とするプロセスの数 */
27.
のチェックは孤児のプロセスグループかのチェックのようだ バックグラウンドの場合の処理 pg_jobcについて、カウントされている場所 fixjobc(struct proc *p, struct pgrp *pgrp, int entering) { ... /* * pが自身のプロセスグループを適任とするか確認するため、pの親をチェックする * もしそうなら、pのプロセスグループのカウントを調整する */ hispgrp = p>p_pptr>p_pgrp; /// hispgrpは親のプロセスグループ if (hispgrp != pgrp && hispgrp>pg_session == mysession) { /// 親と子のプロセスグループは異なり、セッションは同じ場合 if (entering) { /// 対象プロセスが、プロセスグループに加わる場合 pgrp>pg_jobc++; /// pg_jobcをインクリメント p>p_lflag &= ~PL_ORPHANPG; } else if (pgrp>pg_jobc == 0) /// 出る場合はデクリメント orphanpg(pgrp); /// 0に達したなら孤児のプロセスグループ } pg_jobc == 0
28.
バックグラウンドの場合の処理 p = curproc; if (isbackground(p, tp) && ISSET(tp>t_lflag, TOSTOP) && (p>p_lflag & PL_PPWAIT) == 0 && !sigismasked(curlwp, SIGTTOU)) { if (p>p_pgrp>pg_jobc == 0) { error = EIO; mutex_spin_exit(&tty_lock); goto out; } ... 孤児のプロセスグループの場合はエラー番号EIOで シグナルを送信せずに終わる --> TERMIOS(4)の記述と一致
29.
バックグラウンドの場合の処理 /* * プロセスがバックグラウンドの場合、ハングアップさせる */ p = curproc; if (isbackground(p, tp) && /// バックグラウンド且つ、特殊ケースではない ISSET(tp>t_lflag, TOSTOP) && (p>p_lflag & PL_PPWAIT) == 0 && !sigismasked(curlwp, SIGTTOU)) { if (p>p_pgrp>pg_jobc == 0) { /// 孤児のプロセスグループか error = EIO; mutex_spin_exit(&tty_lock); goto out; } mutex_spin_exit(&tty_lock); /// tty_lockのmutexを一旦解放して mutex_enter(proc_lock); /// proc_lockのmutexを取得 pgsignal(p>p_pgrp, SIGTTOU, 1);/// SIGTTOUシグナルを送信 mutex_exit(proc_lock); mutex_spin_enter(&tty_lock); /// tty_lockのmutexを再取得 error = ttypause(tp, hz); /// 1hz待つ mutex_spin_exit(&tty_lock); if (error) goto out; /// pauseの間にエラー goto loop; /// エラー0の場合、最初からリスタート } mutex_spin_exit(&tty_lock);
30.
データの処理
31.
データの処理 /* * 最大でOBUFSIZのチャンク単位でユーザーのデータを処理する。 * 任意の出力変換を行う。 * ハイウォーターマークの記録を付け、オーバーフロー時は * 新しいスペースを獲得を目的にデバイスを待ってsleepする。 */ while (uio>uio_resid > 0 || cc > 0) { if (ISSET(tp>t_lflag, FLUSHO)) { uio>uio_resid = 0; return (0); } if (tp>t_outq.c_cc > hiwat) goto ovhiwat; /* * 前回からの残り物が無ければ、ユーザーからのデータの塊を掴む */ if (cc == 0) { cc = min(uio>uio_resid, OBUFSIZ); cp = obuf; error = uiomove(cp, cc, uio); if (error) { cc = 0; goto out; } } ...
32.
データの処理 while (uio>uio_resid > 0 || cc > 0) { /// まだ転送するデータがある if (ISSET(tp>t_lflag, FLUSHO)) { /// フラッシュ済みなら uio>uio_resid = 0; return (0); /// 転送は正常に終了、関数から戻る } if (tp>t_outq.c_cc > hiwat) /// 出力キューの文字数がハイウォーター goto ovhiwat; /// を越えていたら、エラー処理へ ... uio->uio_residはttwrite()全体での残り転送量。 ccはチャンク単位の転送に分けた、残りの転送量。 #define FLUSHO 0x00800000 /* 出力はフラッシュ済み (状態) */ struct tty { ... struct clist t_outq; /* デバイス出力キュー */ struct clist { .. int c_cc; /* キューの中の文字数 */
33.
データの処理 /* * 前回からの残り物が無ければ、ユーザーからのデータの塊を掴む */ if (cc == 0) { /// 残り物の量は、cc cc = min(uio>uio_resid, OBUFSIZ); /// 最大でOBUFSIZのチャンク量を設定 cp = obuf; /// u_char obuf[OBUFSIZ]; error = uiomove(cp, cc, uio); /// uioからcpにccの量だけコピー if (error) { cc = 0; goto out; /// エラーがあれば終了処理へ } } cpに次の転送のデータ、ccに転送量が入る uiomove()内で、uio->uio_residの値は更新されている
34.
/* * 手が込んだことが行われる必要がないなら、ttyoutputの処理以外で扱える * それらの文字を掴み、出力キューにただ転送する。 * 特別な処理を要求する文字(char_typeの中でbitで示されている)は、 * ttyoutputを呼ぶ。 * データの塊を処理した後で、^O's がすぐに反映されるようにFLUSHOを探す。 */ mutex_spin_enter(&tty_lock); while (cc > 0) { if (!ISSET(tp>t_oflag, OPOST)) ce = cc; else { ce = cc scanc((u_int)cc, cp, char_type, CCLASSMASK); /* ceがゼロなら、ttyoutputで特殊文字を処理する */ if (ce == 0) { tp>t_rocount = 0; if (ttyoutput(*cp, tp) >= 0) { /* 容量不足 */ ... } cp++; cc; if (ISSET(tp>t_lflag, FLUSHO) || tp>t_outq.c_cc > hiwat) { mutex_spin_exit(&tty_lock); goto ovhiwat; } continue; }
35.
データの処理 mutex_spin_enter(&tty_lock); while (cc > 0) { /// ccが無くなるまで繰り返す if (!ISSET(tp>t_oflag, OPOST)) /// OPOSTが設定されていなければ ce = cc; /// 全ての文字を変更無く送信する else { ... TERMIOS(4) より 出力モード OPOST /* 続く出力処理を有効にする
*/ ONLCR/* NL を CR-NL に変換する (ala CRMOD) */ OCRNL /* CRを NL に変換する */ OXTABS /* タブをスペースに置き換える */ ONOEOT /* 出力上の EOT (^D) を捨てる */ ONOCR/* 最初の列で CRを送信しない */ ONLRET /* 端末上で NL は CRの機能をする */ OPOSTがセットされると、残りのフラグが解釈される。 そうでなければ文字は変更せずに送信される ceは特殊文字を含まない、送信される文字数
36.
データの処理 mutex_spin_enter(&tty_lock); while (cc > 0) { /// ccが無くなるまで繰り返す if (!ISSET(tp>t_oflag, OPOST)) ce = cc; else { /// OPOSTは設定されている ce = cc scanc((u_int)cc, cp, char_type, CCLASSMASK); /// char_typeのテーブルでスキャン ... SCANC(9) より int scanc(size_t size,
const u_char *cp, const u_char table[], int mask); scanc() 関数は、長さが sizeのバイト文字列 cp をスキャンする 文字列中の文字は 256byteの tableの index として使われる テーブルの値と mask のAND(論理積)がゼロでないか、 文字列が無くなった時に、スキャンは止まる scanc() 関数はスキップされた文字数を返す
37.
データの処理 ce = cc scanc((u_int)cc, cp, char_type, CCLASSMASK); #define E 0x00 /* Even parity. */ /// mask外 #define O 0x80 /* Odd parity. */ /// mask外 ... #define CCLASSMASK 0x3f /// maskは6bit ... #define BS BACKSPACE /// 2 #define CC CONTROL /// 1 #define CR RETURN /// 2 #define NA ORDINARY | ALPHA /// 0 | 0x40 mask外 #define NL NEWLINE /// 3 #define NO ORDINARY /// 0 mask外 #define TB TAB /// 4 #define VT VTAB /// 5 .... unsigned char const char_type[] = { E|CC, O|CC, O|CC, E|CC, O|CC, E|CC, E|CC, O|CC, /* nul bel */ O|BS, E|TB, E|NL, O|CC, E|VT, O|CR, O|CC, E|CC, /* bs si */ ... E|NO, O|NO, O|NO, E|NO, O|NO, E|NO, E|NO, O|NO, /* ( / */ mask外 E|NA, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* 0 7 */ mask外 ... O|NA, E|NA, E|NA, O|NA, E|NA, O|NA, O|NA, E|NA, /* p w */ mask外 E|NA, O|NA, O|NA, E|NO, O|NO, E|NO, E|NO, O|CC, /* x del */ mask外 ...
38.
データの処理 while (cc > 0) { ... ce = cc scanc((u_int)cc, cp, char_type, CCLASSMASK); /* ceがゼロなら、ttyoutputで特殊文字を処理する */ if (ce == 0) { ... scanc()はcpの先頭からスキャンし、特殊文字が見つかった時点で返る scanc()はスキップされた文字数を返すので、 ccから減算すると、cp先頭からの特殊文字でない文字数を得られる ceがゼロなら、cpの先頭に特殊文字がある
39.
データの処理 /* ceがゼロなら、ttyoutputで特殊文字を処理する */ if (ce == 0) { /// 先頭が特殊文字 tp>t_rocount = 0; /// 行countをリセット if (ttyoutput(*cp, tp) >= 0) { /// 1文字分ttyoutput /* 容量不足 */ mutex_spin_exit(&tty_lock); goto overfull; /// 失敗した場合、エラー処理へ } cp++; /// バッファのポインタを進める cc; /// 残り文字数を減らす if (ISSET(tp>t_lflag, FLUSHO) || /// フラッシュ済み、または tp>t_outq.c_cc > hiwat) { /// キューがハイウォーター mutex_spin_exit(&tty_lock); /// を越えていたら、エラー処理へ goto ovhiwat; } continue; /// 特殊文字を1文字処理したらスキャンから再開 } } /* * 必要に応じて出力処理(タブの展開、改行処理)をしつつ、端末に1文字出力する。 * 成功すれば0より小さい値を返し、そうでなければ再送すべき文字を返す。 * 再帰的でなければならない。 */ int ttyoutput(int c, struct tty *tp)
40.
データの処理 while (cc > 0) { if (!ISSET(tp>t_oflag, OPOST)) /// OPOSTフラグ無しなら ce = cc; /// 文字の変更無し else { ce = cc scanc((u_int)cc, cp, char_type, CCLASSMASK); /// 特殊文字をスキャン if (ce == 0) { ... /// ceがゼロなら特殊文字を処理する continue; } } /* * (処理するチャンクには)一束の通常の文字が見つかっている。 * 出力キューに一斉に転送して、ループの先頭に戻って処理を継続する。 * このOBUFSIZ以下のチャンク内に更なる文字がある場合には、 * 最初の物はttyouputによる特別な扱いを必要とする文字であるはずだ。 */ ... /// 出力キューへの転送処理 } ttstart(tp); mutex_spin_exit(&tty_lock); }
41.
データの処理 /* * (処理するチャンクには)一束の通常の文字が見つかっている。 * 出力キューに一斉に転送して、ループの先頭に戻って処理を継続する。 * このOBUFSIZ以下のチャンク内に更なる文字がある場合には、 * 最初の物はttyouputによる特別な扱いを必要とする文字であるはずだ。 */ tp>t_rocount = 0; /// 行countをリセット i = b_to_q(cp, ce, &tp>t_outq); /// 出力キューにバッファの通常文字を転送 ce = i; /// ceは転送できたバイト数 tp>t_column += ce; /// 行カウントを進める cp += ce, cc = ce, tk_nout += ce; /// バッファを進め、残り文字数を減算、 /// tk_noutは統計ログ用の端末出力カウント tp>t_outcc += ce; /// 出力キューの統計情報を記録 ... /* * バッファをclist(リングバッファのキュー)にコピーする * 転送できなかったバイト数を返す */ int b_to_q(const u_char *cp, int count, struct clist *clp) struct tty { ... long t_outcc; /* 出力キューの統計情報 */
42.
データの処理 while (cc > 0) { /// ccが無くなるまで繰り返す ... i = b_to_q(cp, ce, &tp>t_outq); /// 出力キューにバッファの通常文字を転送 ... if (i > 0) { /// 転送できなかった文字がある /* 容量不足 */ mutex_spin_exit(&tty_lock); goto overfull; /// エラー処理へ } if (ISSET(tp>t_lflag, FLUSHO) || /// フラッシュ済み、または tp>t_outq.c_cc > hiwat) /// キューがハイウォーター break; /// を越えていたら、ループを抜ける } ttstart(tp); /// ccが無くなるか、breakで抜けて来る /// ttstartでキューに入れたデータの転送をはじめる mutex_spin_exit(&tty_lock); }
43.
終了・エラー処理
44.
終了・エラー処理 out: /* ccがゼロでない場合、offsetとiovポインタが前方に移動してしまったので、 * 私たちはuio構造体を一貫性の無いものにする、しかしそれは問題ない。 * (呼び出しは不足を返すか、新しいuioで再スタートするかのいずれかだろう。) */ uio>uio_resid += cc; /// uioの残り転送量にccを加える。 /// (カウンタだけ増やしてデータを巻き戻さない) return (error); /// errorに入っている値を返す overfull: /* * 私達はリングバッファを使用しているので、出力キューに * これ以上挿入できないならば、リングはいっぱいで誰かが * ハイウォーターマークを正しくセットし忘れたと推測できる。 * これをセットして、通常通り進める。 hiwat = tp>t_outq.c_cc 1; /// hiwatにキューの文字数1を入れる /// 続けてovhiwat処理へ ovhiwat: ...
45.
終了・エラー処理 ovhiwat: mutex_spin_enter(&tty_lock); ttstart(tp); /// ttstartでデータの転送をはじめる /// (hiwatを越えたのでキューを空けたい) /* * これは、FLUSHOがt_lflagにセットされたか、 * ttstart/oprocが同時に起こる(またはとても速い)場合のみ発生する。 */ if (tp>t_outq.c_cc <= hiwat) { /// hiwatより低くなった mutex_spin_exit(&tty_lock); goto loop; /// 最初に戻ってやり直し } if (flag & IO_NDELAY) { /// ディレイ無し指定はエラーで抜ける mutex_spin_exit(&tty_lock); /// (この後、sleepがあるので) error = EWOULDBLOCK; goto out; } error = ttysleep(tp, &tp>t_outcv, true, 0); /// 出力のCondition Variableでsleep mutex_spin_exit(&tty_lock); if (error) goto out; goto loop; /// 最初に戻ってやり直し }
Download now