(57)【特許請求の範囲】
【請求項１】
非同期ロック機能を含むアプリケーションが、アプリケーション・タスクの中断なしにロックを介して資源を更新できるようにする方法であって、
第１のアプリケーション・タスクによって要求される資源がロックされているか否かを、ロックの状態を定義する状態ビットに基づいて判断するステップと、
前記資源がロックされていないときは、前記第１のアプリケーション・タスクが、該第１のアプリケーション・タスクによって要求される資源の更新を実行するステップと、
前記資源がロックされているときは、
前記第１のアプリケーション・タスクが、前記更新をするための要求を前記資源用のロック上の待ち行列に入れるステップと、
前記資源上で前記ロックを保持している第２のアプリケーション・タスクが、前記ロックを解除する前に前記第１のアプリケーション・タスクに代わって前記更新を実行するステップと
を含む方法。
【請求項２】
前記ロックを解除する前に、前記第２のアプリケーション・タスクが資源を更新するための第１の更新ルーチンを実行するステップと、
前記ロックを解除した後に、前記第２のアプリケーション・タスクが資源を更新するための第２の更新ルーチンを選択的に実行するステップと
をさらに含み、
それによってロックの競合を削減する、請求項１に記載の方法。
【請求項３】
前記第２のアプリケーション・タスクからの戻りコードを前記アプリケーションに渡すステップをさらに含む、請求項２に記載の方法。
【請求項４】
前記更新ルーチンを実行するために複数のアプリケーション・タスク・タイプを指定するステップをさらに含み、
それによって多重プログラム言語環境および多重実行環境を選択的に可能にし、アプリケーション・タスクを複数の論理クラスに分割する、請求項２に記載の方法。
【請求項５】
１つまたは複数のユーザ・パラメータを前記アプリケーションから前記更新ルーチンに渡すステップをさらに含む、請求項２に記載の方法。
【請求項６】
sync_flagパラメータを前記アプリケーションから、要求を実行するアプリケーション・タスクに渡すステップを更に含み、前記sync_flagパラメータが、更新要求を実行したのと同じアプリケーション・タスクから呼び出されるか否かを示す、請求項１に記載の方法。
【請求項７】
task_typeパラメータを更新ルーチンを実行するアプリケーション・タスクに選択的に渡すステップを更に含み、前記task_typeパラメータが、どのタイプのアプリケーション・タスクがこの関数を実行中であるかを示す、請求項４に記載の方法。
【請求項８】
最大限に供給されたアプリケーションに応答して、前記ロック上で待ち行列に入れられた非同期更新に対する要求の数を制限するステップをさらに含む、請求項１に記載の方法。
【請求項９】
前記第２のアプリケーション・タスクによって待ち行列に入れられた順序で順次実行されるように、複数のアプリケーション・タスクからの前記ロック上にある複数の更新要求を待ち行列に入れるステップをさらに含む、請求項１に記載の方法。
【請求項１０】
非同期ロック機能を含むアプリケーションが、アプリケーション・タスクの中断なしにロックを介して資源を更新できるようにするためのプログラムを記録したコンピュータ読取り可能な記録媒体であって、
第１のアプリケーション・タスクによって要求される資源がロックされているか否かを、ロックの状態を定義する状態ビットに基づいて判断するステップと、
前記資源がロックされていないときは、前記第１のアプリケーション・タスクが、該第１のアプリケーション・タスクによって要求される資源の更新を実行するステップと、
前記資源がロックされているときは、
前記第１のアプリケーション・タスクが、前記更新をするための要求を前記資源用のロック上の待ち行列に入れるステップと、
前記資源上で前記ロックを保持している第２のアプリケーション・タスクが、前記ロックを解除する前に前記第１のアプリケーション・タスクに代わって前記更新を実行するステップと
を含むプログラムを記録したコンピュータ読取り可能な記録媒体。
【発明の詳細な説明】
【０００１】
【発明の属する技術分野】
本発明は、インターフェース・システムおよび方法に関する。さらに詳細には、タスク切替え、待機、またはＣＰＵスピンを行わずに、共用資源の非同期更新を可能にする、ロックを管理するためのシステムおよび方法に関する。
【０００２】
【従来の技術】
コンピューティング・システムは、コンピュータ・メモリ内に格納されているデータ構造およびオブジェクトの更新を防ぐための構造および方法を提供する。これは一般に、排他ロックを保持しながら（したがって、資源の原子的（atomic）更新を保証しながら）、コンピュータ・メモリに保持されている共用資源を更新することによって行われる。このようなシステムでは一般に、データ構造またはオブジェクトへのアクセスが必要なタスクが、排他ロックが許可されるまでデータ構造またはオブジェクトの更新を待つ必要があり、したがってシステムにエラーが導入される可能性のある環境下でしばしば待機タスクを中断させる必要がある。
【０００３】
したがって当技術分野では、システムのパフォーマンスを向上させるためにロックを待つタスクをなくすまたは減らすためのシステムおよび方法が必要である。さらに、なんらかの理由でタスクが待機するのを妨げられている場合は、タスクが排他ロックを待つことなく、共用資源が更新されるようにすることが望ましい。このようなタスクは、システムにある種のエラーを導入することなく、ロックを待ちながら中断することができないことがある。
【０００４】
【発明が解決しようとする課題】
本発明の一目的は、ロックを管理するための改善されたシステムおよび方法を提供することである。
【０００５】
本発明の他の目的は、パフォーマンスが向上したロックを管理するためのシステムおよび方法を提供することである。
【０００６】
本発明の他の目的は、形式的なタスク中断またはＣＰＵスピンを回避する、ロックを管理するためのシステムおよび方法を提供することである。
【０００７】
本発明の他の目的は、費用のかかるロック競合オーバヘッドを回避する、ロックを管理するためのシステムおよび方法を提供することである。
【０００８】
本発明の他の目的は、同期的および非同期的にロックを管理するためのシステムおよび方法を提供することである。
【０００９】
【課題を解決するための手段】
本発明のシステムおよび方法によれば、アプリケーションは、要求されたロックを保持する第２のタスクが第１のタスクに代わって実行するための更新要求を選択的に待ち行列に入れることによって、タスク中断またはタスク切替えを行わずに、排他ロックを使用して資源を更新する。
【００１０】
【発明の実施の形態】
本発明の好ましい実施形態によれば、原子的にただし必ずしも同期的である必要のない、先着順サービス方式でタスクが共用資源を順次更新できるようにするインターフェース・システムおよび方法が提供される。このインターフェース・システムおよび方法では、呼出し側タスクが実際に更新を実行するタスクである必要のない形で行われる、更新を記述する。したがって更新は、呼出し側タスクに対して非同期的に実行することができる。
【００１１】
大部分の標準的なロック・パッケージでは、ロック待機タスクは何らかのデータ構造で表され、何らかの種類の待ち行列上に置かれる。本発明の好ましい実施形態によれば、要求されたロックが現在のタスクによって保持される場合には呼出し側タスクを待ち状態に置くのではなく、呼出し側タスクの代わりに実行される更新の記述が待ち行列に入れられる。すなわち、更新が呼出し側タスクに対して非同期に実行されるが、呼出し側タスクは待機する必要がないという意味である。そうではなく、現在のタスクは（現在ロックを保持しているタスクが）ロックを解除する前に呼出し側タスクに代わって更新を実行するので、更新が原子的に、順次、先着順サービス方式で実行されることが保証される。
【００１２】
本発明の代替実施形態によれば、本発明の非同期的更新システムおよび方法を使用することができるアプリケーションの数は、これを標準の同期（従来技術）ロック機構と共に実装することによって増大する。
【００１３】
コンピュータ・メモリ内の資源は、ロックによって保護されている。一般に、ロックは３コンピュータ・ワードである。合計バイト数はハードウェアによって異なる。たとえば、ＩＢＭ  ＭＶＳオペレーティング・システムでは、３ワードのロックには１２バイトの記憶域が必要である。
【００１４】
アプリケーションは、下記関数呼出しによってロックを初期設定する。
lock_Init(@_of_lock, Max_Queuing)
【００１５】
上式で、
@_of_lockは資源を保護するロックのアドレスである。
【００１６】
Max_Queuingは、資源に対する非同期更新を実行することのできる待ち行列の最大量である。呼出側が無制限の待ち行列を希望する場合は、これを特別値−１に設定することができる。
【００１７】
前述のように、本発明の好ましい実施形態は、標準の（従来技術の）ロック機構もサポートしている。たとえば、呼出側は書込みモードまたは読取りモードでロックを取得し、下記の呼出しを介してロックを即時に取得できない場合は中断することができる。
lock_ObtainWrite(@_of_lock)
lock_ObtainRead(@_of_lock)
lock_ReleaseWrite(@_of_lock)
lock_ReleaseRead(@_of_lock)
【００１８】
上式で、
@_of_lockは、資源を保護するロックのアドレスである。
【００１９】
本発明の好ましい実施形態によれば、非同期更新モードを可能にするために、呼出側は呼び出されて様々な更新を実行する関数を指定する。たとえば、呼出側がリンク・リストに追加するかまたはリンク・リストから除去したい場合は、add_listおよびremove_listの２つの関数が非同期更新機能に定義される。さらに複雑なデータ構造の場合は、さらに多くの関数が定義される。
【００２０】
本発明の好ましい実施形態の追加の特徴は、資源を更新できる様々なタイプのシステム・タスクを呼出側が定義できるようにする。これは、更新が呼出し側タスクとは異なるタイプのタスクによって実行されることがあるので重要である。たとえばＭＶＳには、標準タスクと、異なるプログラミング環境を有するシステム要求ブロック（ＳＲＢ）によって表されるタスクとがある。タスクが様々なプログラミング言語からのコードを実行している多言語アプリケーションでは、別の例が発生する。これにより、様々なタスクが資源を更新できるようになるが、その際にまったく同じルーチンを実行する必要はない。たとえば、リンク・リストへの追加動作には、アセンブラ・コードを実行中のものとは異なる、Ｃ言語コードを実行中のタスクに関するコードが含まれるが、どちらも同じリストを更新する必要が生じることがある。さらに、以下の例で説明するように、非同期更新機能を使用して問題を解決できるようにタスクを分類する際に役立つことがある。
【００２１】
本発明の好ましい実施形態のインターフェースの他の特徴により、共用資源が更新された後およびロックが解除された後に関数が実行されるようにすることができる。これはロックの競合を削減するために必要である。資源を更新するには、ロックが保持されたときの資源の状態に基づく追加処理が必要になることがあるが、その処理はロックを保持しながら実行する必要はない。たとえばリンク・リストからの除去は、ロックを保持しながらオブジェクトをリンク・リストから物理的に除去し、次いでそのオブジェクトを空き記憶域に戻す必要がある。リストを保護するロックを解除した後にオブジェクトを空き記憶域に戻すことによって、ロックの競合が削減される。
【００２２】
本発明の好ましい実施形態の他の特徴は、ロック機能が更新ルーチンに渡すパラメータを指定する機能を含み、さらに資源を更新する際に使用される関数と、ロックが保持されていないときに後処理を実行する関数との間で、情報を渡す機能も含む。
【００２３】
非同期更新機能インターフェース構造
本発明の好ましい実施形態の非同期更新機能インターフェース構造は、１組の関数と、起こり得る資源の更新タイプを表す関連タスク・タイプとを含む。これらの関数およびタスク・タイプは、関数ポインタの２次元配列を含む構造に保存される。各関数には番号が付けられ、配列内の行を表す。各タスク・タイプには番号が付けられ、列を表す。
【００２４】
関数配列を割り振るためのルーチンは下記のテンプレートを有する。
lock_allocate_function_array(work_types, task_types)
【００２５】
上式で、
work_typesは、保護された資源を更新または処理できる様々な更新または後処理ルーチンの番号である。
【００２６】
task_typesは、保護された資源を更新できるタスクに定義された様々なタスク・タイプの番号である。
【００２７】
lock_allocate_function_arrayルーチンは、２次元配列の記憶域を格納する構造のアドレスを戻す。タスク・タイプが１つしかないリンク・リストの例では、work_typesは３になり（空き記憶域に関する追加、除去、および戻りの場合）、task_typesは１になる。
【００２８】
ロック機能に定義されるあらゆる関数は（その関数がロックの保持中に実行される関数であれ、ロックが解除された後に実行される後処理関数であれ）、下記のテンプレートを有する。
0004042945.tif 000002
【００２９】
上式で、
routine_nameは、手順または関数の名前である。
【００３０】
sync_flagは、更新要求を実行したのと同じタスクから呼び出されるか否かを示す、ロック機能によって関数に渡される指示である。これは、値TRUEまたはFALSEのいずれかを有する。
【００３１】
task_typeは、どのタイプのタスクがこの関数を実行中であるかを関数に示す。資源の更新は非同期に実行できるので、更新関数は呼出側と異なる定義済みタスク・タイプ上で実行されることがある。
【００３２】
prc_arg1は、以前の戻りコードまたは引数１である。この関数がロックの保持中に実行される資源更新関数である場合、これは第１のユーザ供給引数である。この関数が後処理ルーチンである場合、これは更新関数によって提供される戻り値である。これは機械ワードであって、ＭＶＳの場合は、記憶域のアドレスまたはその他何らかの関連する値を格納することができる４バイトの情報である。
【００３３】
arg2は、ロックの保持中に実行される資源更新関数である場合は、第２のユーザ供給引数であり、後処理ルーチンである場合は、ルーチンへの唯一のユーザ供給引数である。
【００３４】
これらの関数は、戻りコードを戻すように定義され、たとえば機械のハードウェア・ワードとして実装される。資源を更新する関数（その資源へのロックを保持しながら実行される関数）は、戻りコードprc_arg1を後処理関数（別名ルーチン）へ渡し、これによって資源更新関数と後処理関数との間の通信が可能になる。下記の特殊な戻りコードが定義される。
【００３５】
WORK_NOPOSTWORK (-1)  資源更新関数がこの戻りコードを戻すと、後処理ルーチン（指定されている場合）は呼び出されない。これによって、後処理ルーチンのバイパスが可能になり、関数呼出しに必要なパス長さを保存する。
【００３６】
WORK_DONTUNLOCK (-2)  この戻りコードは、資源更新関数を実行した後に資源をロック解除しないようにロック機能に伝える。通常、ロック機能は資源更新ルーチンを実行した後にロックを解除する。この戻りコードは、ロックを保持したままにする（すなわち、呼出しコードはこれがいつか解除されることを保証しなければならない）。この戻りコードは、本発明の好ましい実施形態の重要な機能であるネストされたロックを、資源更新呼出しが使用できるようにする。資源の更新中は、複数のロックを取得する必要がある場合が多い。この戻りコードを使用すると、共用資源を非同期に更新する前に複数のロックを取得できる。下記に記載する例では、ネストされた非同期ロックに不可欠なこの特徴の使用方法を示す。
【００３７】
呼出しアプリケーションは、下記の関数呼出しを介して各タイプのタスクに使用する関数を指定する。
0004042945.tif 000003
【００３８】
上式で、
work_typeは、プログラマによってこのタイプの更新に割り当てられる番号（０、１、．．．）である。
【００３９】
task_typeは、関数に関連付けられたタスクのタイプに割り当てられる番号である。
【００４０】
functionは、関数のアドレスである。
【００４１】
function_arrayは、この関数が追加される関数配列のアドレスである。これは、lock_allocate_function_arrayから戻されるアドレスである。
【００４２】
リンク・リストの例でプログラマは、リンク・リスト関数への追加に０、リンク・リスト関数からの除去に１、空き記憶域関数への戻りに２の、それぞれのwork_typeを割り当てるように選択することができる。タスク・タイプは１つ（０）しかない。したがって、lock_register_workunit関数呼出しがこのリンク・リスト例に対して関数を定義するには、３つの呼出しが必要になる。
【００４３】
本発明の好ましい実施形態のインターフェース構造を使用するには、更新関数と、lock_allocate_function_arrayルーチンへの単一呼出しと、次いでlock_register_workunitルーチンへのＮ個の呼出しとを含むようにプログラムが書き込まれるが、ここでＮは更新タイプの数にタスク・タイプの数を掛けた数である。その後資源は、タスクを中断せずにプログラムが終了するまで、下記のインターフェースを使用して、非同期に繰り返し更新することができる。
【００４４】
資源更新は、下記のインターフェースを介して達成される。
0004042945.tif 000004
【００４５】
上式で、
@_of_lockは、資源を保護するロックのアドレスである。
【００４６】
@_of_functionarrayは、１組の資源更新を含む定義済み関数配列のアドレスである。
【００４７】
task_typeは、呼出しを実行しているタスク・タイプである。
【００４８】
work_typeは、実行される更新に割り当てられた数（これとtask_typeで、資源更新の際に実行する関数を示す）である。
【００４９】
arg1は、第１のユーザ供給引数である。
【００５０】
arg2は、第２のユーザ供給引数である。
【００５１】
post_workは、（work_typeで指定された）更新関数の後にいつか呼び出されるが、関連付けられたロックは保持しない、後処理ルーチンに割り当てられた数である。後処理ルーチンが必要な場合、呼出側は、実行される後処理がないことを意味する特別値NO_FUNCTION (-1)を指定する。
【００５２】
post_argは、後処理ルーチンへのユーザ供給引数である。
【００５３】
rcは、呼出しからの戻りコードである。これは、資源が呼出し側タスクによって同期的に更新された（ロックの競合なし）か、またはロックを保持している現在のタスク上にディスパッチされる（非同期）かを示し、万一に備えて呼出側はこの情報を知ろうとする。
【００５４】
関数の呼出しには、リンケージのオーバヘッド用にある程度のパス長さが必要である。次に、資源をロックし、ロックがフリーである場合とフリーでなければ関数が非同期に呼び出される場合に、呼出側にこれをインラインで更新させる、高速パス・インターフェースについて記載する。これはプログラマにとっては余分な作業であるが、関数呼出しにとってはリンケージ・オーバヘッドをなくすことができるものであり、ロックの競合がない場合は標準的な従来技術のロックよりも長いパスを必要とせずに非同期更新が実行できる。（もちろん、ロックの競合がある場合、非同期更新は同期更新処理よりもかなり高速にこの競合を処理する。）
【００５５】
これらの高速パス・インターフェースを下記に示す。
0004042945.tif 000005
【００５６】
lock_Resourceインターフェースは、下記のような追加の戻りコードを使用して、前述のlock_UpdateResourceに定義したのと同じ引数を使用する。
【００５７】
ロックを意味するWORK_INLINEは排他的モードで取得されるが、ロックに関する競合がないために、更新関数は実行されなかった。その後呼出側は、関数呼出し後にインラインで資源を更新する。
0004042945.tif 000006
【００５８】
unlock_Resourceインターフェースは、資源をロック解除し、ロックが競合なしに解除された場合はWORK_INLINEを戻す。その後呼出側は、後処理コードをインラインで実行する必要がある。そうでない場合、後処理作業は別のタスクを実行するために待ち行列に入れられる。
【００５９】
次に図を参照すると、同期資源更新機能に関連して、本発明の非同期資源更新機能の好ましい実施形態が記載されている。ここでは、非同期機能と同期機能を組み合わせることによって、より高い柔軟性が提供される。当業者であれば明らかなように、同期資源更新が提供されていない場合でも、非同期機能は提供されることがある。
【００６０】
データ構造
図１を参照すると、ロック１００は３つの機械ワード、state １０１、waitq １０２、およびmaxqueued １０３によって定義される。ＩＢＭのＭＶＳオペレーティング・システムでは、１ワードについて４バイトである。state １０１は、ロックの状態を定義する状態ビットを含む。waitqは、wait queue ４０４（図４５）、待機タスクのＬＩＦＯ待ち行列（同期的な従来技術のロック・ウェイタ）、または資源更新（非同期更新）のアンカである。maxqueued １０３は、非同期更新呼出しが待機させられる前に待ち行列に入れることのできる更新要求の最大数を指定する。maxqueued値が−１の場合は、無制限であることを示す。
【００６１】
図２を参照すると、state １０１は、Ｅ  １２１、Ｗ  １２２、Ｌ  １２３、Ｐ  １２４、およびＲ  １２５の各値を含む３２ビット・ワードを含み、ここでフィールドＥ  １２１内のビットはロック１０１が排他的（書込み）に保持されていることを示し、フィールドＷ  １２２内のビットは待機待ち行列が空でないことを示し、フィールドＬ  １２３内のビットはロックが優先順位の高い状態に保持されていることを示し、フィールドＰ  １２４内のビットは、maxqueuedに達しているかまたはこれを超えているために、非同期更新要求が更新を待ち行列に入れるのではなく待機しなければならないことを示す。フィールドＲ  １２５は、ロックを保持するリーダのカウントを格納する。
【００６２】
図３を参照すると、待機作業は、next １０６、prev １０７、ecb １０８、action １０９、type １１０、workfun １１１、workprc １１２、workarg １１３、workrc １１４、funp １１５、postwork １１６、およびpostarg １１７の各フィールドを含む、WAIT_ELEMENTデータ構造１０５によって定義される。next １０６およびprev １０７は、リストまたは待ち行列内に格納された場合の、WAIT_ELEMENT １０５の順方向ポインタおよび逆方向ポインタである。MVSの場合、ecb １０８は、タスクが待機させられるときにWAITに設定されるワードである。action １０９は下記のいずれか１つの値を有する。OBTAINLOCK（１）は、タスクがロックを取得しようとしてロックが別のタスクによって保持されている場合は待機することを示し、RELEASELOCK（２）はタスクがロックを解除しようとすることを示し、DOWNGRADE（３）はタスクがロックをダウングレードしようとすることを示し、UPGRADE（４）はタスクがロックを更新しようとして必要であれば待機することを示し、WORKUNIT（５）は、WAIT_ELEMENT １０５がタスク用ではなく資源用に待ち行列に入れられた作業であることを示す。type １１０は、書込みモードを示すＥＸＣＬＵＳＩＶＥ（ｘ８０００００００）および読取りモードを示すREAD（１）を使用して取得または解除するロックのタイプを指定する。workfun １１１は、資源更新に対するロックが保持されている間に実行するための、関数の配列のインデックスである関数番号を指定する。workprc １１２は、資源更新ルーチンの関数引数番号１である。workarg １１３は、資源更新ルーチンの関数引数番号２である。workrc １１４は、資源更新ルーチンの戻り値である。funp １１５は、lock_allocate_function_arrayによって割り振られる構造である関数配列１３０へのポインタである。postwork １１６は、後処理関数番号である。postarg １１７は、後処理引数である。
【００６３】
図４を参照すると、関数配列１３０は、work_types １３１、task_types １３２、およびarrayp １３３を含む。work_types １３１は配列内にある更新関数の行の総数を指定し、task_types １３２は関数配列内にあるタスク・タイプ列の総数を指定し、arraypは関数アドレスの２次元配列を示すポインタまたはアドレスを提供する。
【００６４】
本発明の好ましい実施形態では、IBM System/390のハードウェア命令であるcompare and swap（ＣＳ）およびcompare double and swap（ＣＤＳ）を使用する。これらの命令は、マルチプロセッサ（ＭＰ）システムのＭＰ安全方式で、それぞれ４バイトまたは８バイトを更新する。他のハードウェア・プラットフォーム上での実装は、同等の命令を使用する。これらの命令は、記憶域内にあるワードまたはダブル・ワードの古い値、新しい値、およびアドレスを取り、古い値が記憶域内のワード（またはダブル・ワード）と比較されて、同じであればそこに新しい値が格納され、同じでなければ命令は失敗に終わる。この実装には別の方法もある。こうしたすべての実装に共通の特徴は、更新関数の呼出しを要求するWAIT_ELEMENT １０５を待ち行列に入れて、更新ルーチンおよび後処理ルーチンの実行を容易にする機能である。
【００６５】
図５を参照すると、lock_UpdateResource手順１４０が記載されている。ステップ１４１では、stateフィールド１０１をnullから排他的に更新するためにＣＳ命令が呼び出される。ステップ１４２では、このＣＳ命令が首尾良く実行されたか否かが判定される。実行されていない場合は、競合を処理するためにステップ１４３でMVS_update １６０が呼び出される。それ以外の場合は、ステップ１４４で資源を更新するためのルーチンが呼び出され、資源更新ルーチンからの戻りコード（rc）が保存される。ステップ１４５では、stateフィールド１０１を排他的からnullに更新するためにＣＳ命令が使用される。ステップ１４６では、ステップ１４５でＣＳ命令が首尾良く実行されたか否かが判定され、実行されていなければ、競合を処理するためにステップ１４８でMVS_unlock １９０が呼び出される。それ以外の場合は、ステップ１４７で後処理ルーチンが指定されたか否かが判定される。指定されていれば、ステップ１４９でステップ１４４から保存された資源更新戻りコードがWORK_NOPOSTWORKに等しいか否かが判定され、等しくない場合はステップ１５０で後処理ルーチンが呼び出される。
【００６６】
以前に定義された高速パス・マクロlock_Resourceおよびunlock_Resourceの実装は、イン・ライン・マクロlock_UpdateResource １４０の実装に等しい。
【００６７】
図６を参照すると、MVS_updateマクロ手順１６０は、ロックがすでに他の何らかの状態で保持されている場合を処理するので、呼出し側タスクはロックを取得できない。これは、lock_UpdateResourceマクロと同じパラメータを取る。ステップ１６１では、WAIT_ELEMENT用に記憶域が取得され、その後、関数番号、タスク・タイプ、引数などの呼出側が指定した情報で充填される。ステップ１６２では、wait queue ４０４にWAIT_ELEMENT １０５を追加するために、またはロックEXCLUSIVEを取得するために、lock_or_wait １７５への呼出しが実行される。actionフィールド１０９はWORKUNITに設定される。ステップ１６３では、lock_or_waitルーチン１７５がWAIT_ELEMENT １０５を待ち行列に入れたか否かが判定される。入れていない場合は、ステップ１６４で資源更新ルーチンが呼び出され、戻りコード（rc）が保存される。ステップ１６５では、stateフィールド１０１を排他的からnull（０）に更新するためにＣＳ命令が使用される。ステップ１６６はこのＣＳ命令が首尾良く実行されたか否かを判定し、実行されていない場合は、ステップ１６７で競合を処理するためにMVS_unlock １９０が呼び出される。それ以外の場合は、ステップ１６８で後処理ルーチンが指定されているか否かを判定し、指定されている場合は、ステップ１６９でステップ１６４からの資源更新戻りコード（rc）がWORK_NOPOSTWORKに設定されているか否かを判定する。設定されていない場合は、ステップ１７１が後処理ルーチンを呼び出し、更新ステップ１６４からの戻りコード（rc）を渡す。ステップ１６９で戻りコードがWORK_NOPOSTWORKであると判定された場合は、ステップ１７０でWAIT_ELEMENTが空き記憶域に戻される。
【００６８】
図７を参照すると、lock_or_waitルーチン１７５は、所望の状態でロックを取得するか、または待機要素１０５をＬＩＦＯ方式でwait queue ４０４に追加する。lock_or_wait １７５には下記のプロトタイプがある。
lock_or_wait(@_of_lock,@_wait,type,action)
【００６９】
上式で、
@_of_lockは、ロックのアドレスである。
【００７０】
@_waitは、WAIT_ELEMENT構造のアドレスである。
【００７１】
typeは、取得するロックのタイプ（EXCLUSIVE、READ、またはLOCKED）である。
【００７２】
actionは、OBTAINLOCK、RELEASELOCK、WORKUNITなどである。
【００７３】
typeがLOCKEDに設定された場合は、EXCLUSIVEよりも高位の特殊な状態であり、他のどんなタスクもlock stateフィールド１０１を更新しないことを示す。
【００７４】
ステップ１７６では、stateフィールド１０１およびwaitqフィールド１０２がoldstate ４２３およびoldqueue ４２４にそれぞれ保存される。ステップ１７７は、ロック済みビット１２１がoldstate ４２３に設定されているか否かを判定する。設定されていれば、WAIT_ELEMENT １０５がwait queue ４０４の先頭に追加され、newqueue ４０３に保存される。ステップ１８１で、newstate ４２１がoldstate ４２３と等しく設定され、ステップ１８３で、待機ビット１２２がnewstate ４２１に設定される。ステップ１８４では、ＣＤＳコマンドを使用してoldstate ４２３のロックをnewstate ４２１の値に更新する。ステップ１８５は、このＣＤＳコマンドが首尾良く実行されたか否かを判定し、実行された場合は、ステップ１８６で、WAIT_ELEMENT １０５がwait queue ４０４の待ち行列に入れられたことを示すように、戻り指示が設定される。実行されなかった場合は、処理がステップ１７７に戻る。ステップ１７７で、ロック済みビット１２１がoldstate ４２３に設定されていないことが判定されると、ステップ１７８で、oldstate ４２３のstateビット１０１に基づいて、ロックが所望の状態で取得できるか否かを判定する。取得できない場合は処理がステップ１７９に戻り、それ以外の場合は、ステップ１８０でoldstate ４２３および入力タイプ（排他的となる）に基づいてnewstate ４２１が設定され、ステップ１８２でnewqueue ４０３がoldqueue ４２４に等しく設定される。次いで処理はステップ１８４に進み、ここでＣＤＳコマンドを使用してロックをoldqueue ４２４からnewqueue ４０３に更新し、ステップ１８６で、WAIT_ELEMENT １０５の状態が更新されたことを示す指示を戻す。
【００７５】
一般に、lock_or_wait １７５を通じたループは、ステップ１７９でWAIT_ELEMENT １０５をwait queue ４０４に追加するか、またはステップ１８２でlock stateフィールド１０１を呼出側が所望の状態に更新する。ステップ１８６では、何が実行されたかを示す指示を戻す。一般にステップ１７７がLOCKEDビットがstateフィールドに設定されていると判定すると、WAIT_ELEMENTは待ち行列に入っていなければならない。設定されていない場合、呼出側はロックを所望のモードで取得することが可能であり、ステップ１７８で、ロックが所望のモードで取得できるか否かを調べるためにstateが検査される。たとえば、ロックがすでに読取りにロックされている場合、ロックEXCLUSIVEを取得しようとするタスクは、WAIT_ELEMENT １０５を待ち行列に入れなければならない。
【００７６】
図８に示す構成を有する図９ないし図１７を参照すると、タスクがロックを解除しようと試みて、wait queue ４０４上にWAIT_ELEMENTがあるかまたはロック状態がLOCKEDビットに設定されていることがわかると、いつでもMVS_unlock １９０が呼び出される。作業の大部分は、WAIT_ELEMENTを待ち行列から出して処理する必要があるので、実際にはロック解除ルーチン内にある。MVS_unlockプロトタイプは下記のとおりである。
0004042945.tif 000007
【００７７】
上式で、
@_of_lockは、解除されるロックのアドレスである。
【００７８】
typeは、実行するロック解除のタイプ（EXCLUSIVE、DOWNGRADE、またはREADのいずれか）である。
【００７９】
function_arrayは、ロックに関連付けられた資源関数を含む関数配列のアドレスである。
【００８０】
task_typeは、呼出しを実行するタスクのタイプである。
【００８１】
post_workは、後処理関数の番号である。
【００８２】
prcは、資源更新ルーチンからの戻りコードである。
【００８３】
post_argは、後処理関数の引数である。
【００８４】
MVS_unlock １９０は、通常の同期ロックおよびロック解除、ならびに資源更新ルーチンを実行中に保持されたロックのロック解除を処理する。MVS_unlock １９０は、処理が完了したことを理解するまで繰り返しループされる。
【００８５】
図４５を参照すると、本発明の好ましい実施形態により、WAIT_ELEMENT １０５は、taken queue（取得待ち行列）４００、unlock queue（ロック解除待ち行列）４０１、return queue（戻り待ち行列）４０２、new queue（新規待ち行列）４０３、wait queue（待機待ち行列）４０４、およびpost queue（ポスト待ち行列）４０５を含む、いくつかの待ち行列とリストとの間で選択的に移動される。これらの待ち行列は、図のように、takenHead ４１０、takenTail ４１１、unlockHead ４１２、unlockTail ４１３、returnHead ４１４、returnTail ４１５、newTail ４１６、waitq １０２、postHead ４１７、およびpostTail ４１８によってアンカされている。
【００８６】
taken queue ４００は、MVS_unlock １９０がwait queue ４０４から取り去ったが処理していないすべてのWAIT_ELEMENT １０５を含む。この待ち行列４００は、takenHead ４１０およびtakenTail ４１１によって二重にリンクされているため、先頭から末尾の先入れ先出し（ＦＩＦＯ）順または末尾から先頭への後入れ先出し（ＬＩＦＯ）順を逆にすることができる。
【００８７】
newTail ４１６はロックwaitqフィールド１０２から取得された待ち行列アンカのコピーを有する変数である。newTail ４１６はLIFO new queue ４０３の先頭である。
【００８８】
unlockHead ４１２およびunlockTail ４１３によってアンカされているunlock queue ４０１は、ロック解除要求またはダウングレード要求のＦＩＦＯ待ち行列である。
【００８９】
postHead ４１７およびpostTail ４１８によってアンカされているpost queue４０５は、覚醒される必要のある待機タスクを表すかまたは、ロックが保持されていない間に実行される後処理ルーチンを記述するWAIT_ELEMENTの待ち行列である。
【００９０】
returnHead ４１４およびreturnTail ４１５によってアンカされているreturn queue ４０２は、完全に処理されて空き記憶域に戻される必要のあるWAIT_ELEMENTのリストである。
【００９１】
図９ないし１７を参照すると、MVS_unlock １９０はステップ１９１で、WAIT_ELEMENT用の記憶域を取得し、type（EXCLUSIVE、READ）およびaction（RELEASELOCKまたはDOWNGRADE）に基づいてこれを初期設定する。
【００９２】
ステップ１９２では、ロックをLOCKED状態で取得するか、またはactionに基づいてWAIT_ELEMENTをwait queue ４０４に追加するために、lock_or_wait １７５が呼び出される。
【００９３】
ステップ１９３は、lock_or_wait １７５がWAIT_ELEMENT １０５を待ち行列に入れたか否かを判定する。入れていない場合は、ステップ１９４で、takenHead ４１０およびtakenTail ４１１がゼロ（null）に初期設定され、ステップ１９５で、WAIT_ELEMENT １０５がreturn queue ４０２に追加されてreturnHead ４１４およびreturnTail ４１５が適切に調整され、ステップ１９６で、ロックが解除されるかまたは所望のstateにダウングレードされて、そのstateがロック解除を反映するように更新される。ステップ１９７では、lock stateおよびwaitqアンカ１０２がそれぞれoldstate ４２３およびoldqueue ４２４に保存される。
【００９４】
ステップ１９８は、old queue ４２４がnullであるか否かを判定し、nullでない場合は、ステップ１９９でnewTail ４１６がold queue ４２４に等しく設定され、ステップ２０１でnew queue ４０３がnullに設定され、ステップ２０４でnew state ４２１がold state ４２３に等しく設定され、処理は下のステップ２１０に進む。ステップ１９８でold queue ４２４がnullでないと判定されると、ステップ２００でnewTail ４１６はnullに設定され、ステップ２０２でnew queue ４０３はtakenTail ４１１に等しく設定される。
【００９５】
ステップ２０３は、takenTail ４１１がnullか否かを判定し、nullであれば、ステップ２０６でnew state ４２１がold state ４２３に等しく設定され、ステップ２０８でnew state ４２１のロック済みビットと待機ビットがオフにされる。処理はその下のステップ２０９に進む。ステップ２０３で、takenTailがnullでないと判定されると、ステップ２０５でnew state ４２１がold state ４２３に等しく設定され、ステップ２０７でnew state ４２１のロック済みビットがオフにされて、処理はステップ２０９に進む。
【００９６】
ステップ２０９では、new state ４２１の防止ビットがオフにされ、処理はステップ２１０に進む。ステップ２１０では、lock stateおよびwaitq １０２で、oldvaluesをoldstate ４２３またはoldqueue ４２４に等しく設定し、newvaluesをnewstate ４２１またはnewqueue ４０３に等しく設定するために、ＣＤＳコマンドが呼び出される。
【００９７】
ステップ２１１は、ＣＤＳ呼出しが首尾良く実行されたか否かを判定し、実行されなかった場合、処理はステップ１９８に戻る。ＣＤＳ呼出しが首尾良く実行された場合は、ステップ２１２でnew tail ４１６がnullであるか否かを判定し、nullでなければステップ２１３で処理はnew queue ４０３にあるすべてのエントリを介してループされ、obtainlockおよび作業ユニットWAIT_ELEMENTをtaken queue ４００の末尾に追加し、任意のダウングレード要求またはロック解除要求をunlock queue ４０１に追加して、任意のアップグレード要求をtaken queue ４００の先頭に追加する。このループ２１３中に、taken queue ４００内にある要求の数がカウントされ、ステップ２１４では、要求の数がロック１００のmaxqueued １０３を超えた場合、作業ユニットを同期的に実行させるためにstate １０１の防止ビット１２４はオンになる。ステップ２１５は、unlock queue ４０１内のすべてのエントリをループし、要求（ダウングレードまたは解除される）を処理し、解除またはダウングレードを反映するようにlock state １０１を更新して、処理されたエントリ（WAIT_ELEMENT）はreturn queue ４０２に移動される。ステップ２１６ではunlockHeadがnullに設定され、ステップ２１７ではunlockTailがnullに設定される。ステップ２１８は、lock state １０１の排他的ビット１２１およびリーダ・カウント１２５がどちらもnullであるか否かを判定し、nullでない場合は処理が下のステップ２２０に進み、nullである場合は、待ち行列に入れられたWAIT_ELEMENTに指定された資源更新ルーチンを呼び出すために、ステップ２１９がtaken queue ４００を介してループし、作業ユニット用でない（ロック取得要求用の）WAIT_ELEMENTに達するまで、関連付けられた戻りコードをWAIT_ELEMENTに保存し、残りのどんなWAIT_ELEMENTもpost processing queue ４０５の末尾に追加され、更新ルーチンがWORK_DONTUNLOCKを戻すとこのループは終了し、ロックを確実にするためにlock state １０１に設定された排他的ビット１２１は、次の非同期ロック要求に備えて保持されたままになる。
【００９８】
ステップ２２０はtaken queue ４００を介してループされ、指定されたロック・タイプが待ち行列に入っているWAIT_ELEMENTのロック・タイプと競合しない場合は、任意の待機タスクを覚醒し、競合する場合はループが終了する。任意の処理済みWAIT_ELEMENTがpost queue ４０５の先頭に追加され、処理はステップ１９７に戻る。
【００９９】
ステップ２１２で、newTail ４１６がnullでないと判定されると、ステップ２２１はpost queue ４０５を介してループされ、任意の待機タスクを覚醒し、ロック・ウェイタ用のWAIT_ELEMENTをpost queue ４０５から除去し、それらをreturn queue ４０２に追加する。ステップ２２２は、MVS_unlock １９０が後処理ルーチンで呼び出されたか否かを判定し（post_workはNO_FUNCTIONに等しくない）、呼び出されていない場合、処理はその下のステップ２２５に進み、呼び出された場合、ステップ２２３でMVS_unlockに渡されたprcがWORK_NOPOSTWORKに等しかったか否かを判定し、等しかった場合、処理はステップ２２５に進み、等しくなかった場合ステップ２２４で、入力によってMVS_unlockに渡された後処理ルーチンが呼び出される。
【０１００】
ステップ２２５はpost queue ４０５を介してループされ、指定されたルーチンがなく、資源更新関数がWORK_NOPOSTWORKを戻さなかった場合は、作業ユニット用の任意の後処理ルーチンを実行し、処理済み作業ユニット（WAIT_ELEMENT）をpost queue ４０５からreturn queue ４０２へ移動する。ステップ２２６は、return queue ４０２内のすべてのWAIT_ELEMENTを空き記憶域に戻す。
【０１０１】
【実施例】
本発明の好ましい実施形態の非同期更新機能は、多くのタイプの資源およびアプリケーションに適用可能である。具体的には、資源を更新する必要があるが、更新の結果を待ってタスクを実行する必要がない場合に特に適している。好ましい実施形態では、同じ資源に対して非同期更新関数または標準の同期ロック取得を使用する機能がタスクに与えられている。これによって可能性がかなり拡大される。
【０１０２】
タスクまたはスレッドという用語は、コンピュータ・システム内の作業単位を表す際に使用される。ＩＢＭのＭＶＳオペレーティング・システムでは、WAIT関数はタスクを待機させ、POST関数は待機タスクを覚醒させる。
【０１０３】
実施例１．ロック・ウェイタ・リストの保守
前述のように、本発明の非同期機能は、同期ロック機能を使用して好ましい実施形態にマージされる。
【０１０４】
同期ロック機能の設計は示されていないが、ＤＦＳ／ＭＶＳ環境において、ロック機能は低水準のＭＶＳオペレーティング・システム機能を使用してタスクにロックを待機させる。ＤＦＳはＰＯＳＩＸアプリケーションである。ＤＦＳがプログラム例外を取る場合、ＰＯＳＩＸ機能はこれらの低水準オペレーティング・システム機能でタスク待機を処理するように設計されない（WAIT/POST）。したがって、ＤＦＳロック・パッケージはWAIT_ELEMENTをロックそれ自体の待ち行列に入れるだけでなく、プログラム例外が発生したときに検査できる大域リストにも入れるので、すべての待機タスクを覚醒し、例外について通知することができる。
【０１０５】
図１８を参照すると、タスクがロックを待つ場合、前述のようにlock_or_waitルーチン１７５を使用してそのWAIT_ELEMENTをロックの待ち行列に入れ、さらに待機する前にそのWAIT_ELEMENTを大域リストまたは待ち行列２３０にも追加して、待機後それを大域リスト２３０から除去する。標準同期ロックが使用される場合、大域リスト２３０に関する競合がタスクを待機させるため、タスクは単一ロックについて待機しなければいけない時間の２倍待機することになる可能性がある。これはパフォーマンスにとっては望ましくないことである。
【０１０６】
そこで本発明の好ましい実施形態の非同期更新機能が、大域リスト２３０への追加および大域リスト２３０からの除去に使用される。これを実行するために必要な非同期更新関数には、大域リスト２３０にWAIT_ELEMENT ２３２、２３３、２３５を追加するadd_to_global、大域リスト２３０からWAIT_ELEMENTを除去するremove_from_global、WAIT_ELEMENTを空き記憶域に戻すreturn_wait、ならびにすべてのWAIT_ELEMENTを大域リスト２３０から除去し、ウェイタを覚醒し、それ以上スレッドが待機できないようにPREVENTフラグを設定する、quiesce_globalがある。大域リスト２３０は二重にリンクされたリストであり、globalHead ２３１とglobalTail ２３４のアンカをオフにする。
【０１０７】
図１９を参照すると、単一の定義済みタスク・タイプglobalFuns ２３６が非同期更新関数の４×１配列２３７を作成する。
【０１０８】
図２０を参照すると、スレッドがロック待機に入る必要が生じるごとに、do_wait ２４０が実行される。ステップ２４１は、下記手順を実行する。
lock_UpdateResource (&globalLock, globalFuns, ALL_TASKS,
add_to_global, ０, ((int)waitp), NO_FUNCTION, 0, rc)
【０１０９】
ステップ２４２はecbを待ち、これを受け取るとすぐにステップ２４３が下記手順を実行する。
lock_UpdateResource（&globalLock, globalFuns, ALL_TASKS,
remove_from_global, ０, （（int）waitp）, return_wait, ０,rc）
【０１１０】
このようにして、ロック１００上での待機タスクは、実際にはWAIT呼出し上でそれ自体を中断するだけである。大域リスト２３０へのタスク（WAIT_ELEMENT）の追加およびそこからのタスクの除去は、呼出し側タスクを待機させないことを保証する方法で実行される。lock_UpdateResource １４０への第１の呼出し２４１において、add_to_globalルーチン２４５は更新ルーチンであり、waitpはadd_to_globalルーチン２４５に渡されるWAIT_ELEMENT１０５のアドレスである。後処理ルーチンはまったく必要ない。第２の呼出し２４３において、remove_from_global ２５０はエントリ（WAIT_ELEMENT２３２、２３３、または２３５のうちの１つ）を大域リスト２３０から除去するルーチンであり、return_waitはWAIT_ELEMENTを空き記憶域に戻す後処理ルーチンである。
【０１１１】
図２１を参照すると、（waitp = argである）add_to_globalルーチン２４５はステップ２４６を含み、このステップでpreventフラグがnullであるか否かが判定され、nullである場合は、ステップ２４８が処理されるWAIT_ELEMENTのecbフィールド１０８にあるエラー・コードをポストし、nullでない場合は、ステップ２４７がWAIT_ELEMENT（この場合はタスク２３２）を大域リスト２３０の先頭に追加する。
【０１１２】
図２２を参照すると、（waitp = argである）remove_from_globalルーチン２５０は、preventフラグ１２４がnullか否かを判定するステップ２５１を含む。nullである場合、戻りコード（rc）はゼロに設定され、nullでない場合、このWAIT_ELEMENT（たとえば２３３）は大域リスト２３０から除去される。ステップ２５４では、戻りコード（rc）が呼出側に戻される。
【０１１３】
図２３を参照すると、（waitp = prcである）return_waitルーチン２６０は、waitpがnullであるか否かを判定するステップ２６１を含む。nullでない場合、waitpになるように指示されたWAIT_ELEMENTが空き記憶域に戻される。return_wait ２６０はremove_from_global ２５０の後処理ルーチンであり、remove_from_globalはその戻りコードを介してWAIT_ELEMENTのアドレスを伝え、それが（資源更新機能によって自動的に）prcとしてreturn_waitに入力される。return_wait ２６０はWAIT_ELEMENTを空き記憶域に戻す。ルーチン２６０は後処理ルーチンであるため、ロックを保持している間は空き記憶域への戻りは実行されない。これは、後処理ルーチンの利点を示すものであり、資源更新ルーチンからの戻り値を後処理ルーチンへ渡す。
【０１１４】
図２４を参照すると、quiesce_global ２６５はすべてのウェイタを覚醒し、ステップ２６７で、ステップ２６６で１に設定されるpreventフラグ１２４により、エラーが原因でプログラムが終了していることをそれらに伝える。ステップ２６８でポインタ２３１および２３４がクリアされるので、大域リスト２３０は空になる。
【０１１５】
実施例２．待ち行列を保持する入出力装置の管理
この例は、１９９９年１０月２９日出願のS. T. Marcotteによる「System and Method for Application Influence of I/O Service Order Post I/O Request」という名称の米国特許出願第０９／２４０７１９号（譲受人整理番号ＥＮ９９８１３７）に記載のシステムに関する。Marcotteは、装置宛に発行された入出力の数が、そこに記載されている入出力ドライバを使用するアプリケーションによって調整可能な数であるMax_Issuedよりも多い場合に、保留入出力を待ち行列に入れる装置上に保持待ち行列を有する入出力待ち行列システムについて記載している。
【０１１６】
図２５を参照すると、この例では、max_issuedカウント２８７、current_issuedカウント２８８、およびdevice_lock ２８９と共に、holdHead ２７１およびholdTail ２７４によってアンカされた、aevent ２７２、２７３、２７５の保持待ち行列２７０が提供されている。max_issuedは装置に送信される最大数の入出力動作を記憶し、current_issuedカウント２８８は実際に装置に発行された入出力イベントの数を記憶する。current_issued ２８８がmax_issued ２８７に等しいかまたはこれよりも大きい場合、入出力動作（aevent）は装置に直接送信されずに保持待ち行列２７０に追加される。入出力が完了すると、入出力ドライバは、current_issued ２８８がmax_issuedカウント２８７よりも少ない場合に、保持待ち行列２７０から第１の入出力（aevent ２７２）を取るためににコードを実行する。
【０１１７】
呼出しアプリケーションは、current_issueカウント２８８がmax_issuedカウント２８７を超えている場合でも保持待ち行列２７０を迂回することができるので、待ち行列に関するほぼすべての制御をアプリケーションに与える。さらに、呼出しアプリケーションは、current_issued ２８８がmax_issued ２８７を超える場合であっても、後で入出力（aevent）を保持待ち行列２７０から装置へ移動することが可能で、これによって呼出しアプリケーションは入出力が発行された後にこれを再オーダすることができる。
【０１１８】
保持待ち行列２７０、Max_Issued ２８７、およびCurrent_Issued ２８８は、本発明の好ましい実施形態の非同期資源更新機能を使用して、ロックによって管理することができる。このシステムでは、入出力が装置側で完了すると、オペレーティング・システム（ＭＶＳ）がＳＲＢと呼ばれる特別なタスクをディスパッチし、入出力ドライバはＣコードで書き込まれ、Ｃタスクを使用するのに対して、入出力完了を処理するためのシステムのＳＲＢコードはアセンブラで書き込まれ、Ｃとは異なる実行環境を有する。したがってこの解決策では２つのタスク・タイプ（ＣタスクおよびＳＲＢタスク）が定義され、複数の定義済みタスク・タイプ１１０を有する利点について例示している。入出力ドライバはこれらの非同期更新機能タスクを使用して入出力保持待ち行列を管理し、同期ロックを取得するために中断する必要はまったくない。これによって、パフォーマンスが向上し、システムの入出力完了ＳＲＢを中断する必要がなくなる。
【０１１９】
aeventデータ構造は、保留入出力を表すために使用される。このaeventデータ構造は、入出力動作に関係するすべての関連情報を記述し、タスクが処理を続行する前に完了するために入出力を待機する必要がある場合に待機を続けるためのＥＣＢを有する。したがって、タスクは入出力を待機しなければならない場合があるが、入出力待ち行列の更新を待機する必要は決してない。この特有の実施形態では、Max_issuedが２に設定され、これによって最高のパフォーマンスが提供される。提供された資源更新ルーチンは、queue_io ２８０、issue_io ２９０、schedule_io ３００、およびschedule_first_io ３１０を含む。これらについて、それぞれ図１８、１９、２０、および２１に関して下記で詳細に説明する。
【０１２０】
queue_io ２８０は、新しい入出力動作を入出力システムに導入するために呼び出されるルーチンである。これは、呼出側が、待ち行列が迂回されるかまたはCurrent_issued ２８８がMax_Issued ２８７より小さいかを問わなかった場合は、保持待ち行列に入出力を追加する。
【０１２１】
issue_io ２９０は、オペレーティング・システム装置に入出力を発行する後処理ルーチンである。
【０１２２】
schedule_io ３００は、（Current_Issued ２８８またはMax_Issued ２８７の値に関係なく）入出力を保持待ち行列２７０から装置へ移動するためか、あるいは入出力（aevent）を装置へ送信するのではなく保持待ち行列２７０から除去することによってこれを取り消すために呼び出される。
【０１２３】
schedule_first_io ３１０は、１つの入出力が完了し（すなわち、装置へ送信される入出力が１つ少なくなる）、Current_IssuedおよびMax_Issuedの値に応じて、最初の１つを保持待ち行列から取る際に呼び出されるルーチンである。
【０１２４】
図２６の例を参照すると、function_array ２７９は、４つの更新タイプ（２８０、２９０、３００、および３１０）に２つの各タスク・タイプ（ＣタスクまたはＳＲＢ）を掛けた、４×２配列の関数である。
【０１２５】
一般にアプリケーションは、新しい入出力を発行する必要がある場合、下記の非同期資源更新呼出しを発行する。
lock_UpdateResource (&adevice->lock, ioFuns, CTASK,
queue_io, 0, ae, issue_io, ae, rc);
【０１２６】
上式で、aeは入出力動作を表すaevent構造のアドレスであり、このコードはＣタスク上で実行され、後処理ルーチンissue_ioは装置に対して入出力を発行する。
【０１２７】
アプリケーションが入出力を取り消したいか、または入出力が装置へ送信中であることを確認したい場合は、下記の呼出しを実行する（これによってアプリケーションは、たとえば待ち行列の中間から入出力を移動することで、入出力の順番に影響を与えることができるようになる）。
lock_UpdateResource (&devp->lock, ioFuns, CTASK,
schedule_io, 0, ae, issue_io, ae, rc);
【０１２８】
上式で、この場合もaeはaevent構造のアドレスであり、このコードはＣタスク上で実行され、aeventは取消しが要求されたか否かを示す（この場合、入出力は装置にいっさい送信されない）。
【０１２９】
入出力が完了すると、システムは、入出力保持待ち行列をチェックして（前述のように、Max_Issued ２８７およびCurrent_Issued ２８８に応じて）第１の入出力を装置にスケジューリングできる、ＳＲＢをスケジューリングする。下記の呼出しを実行する。
【０１３０】
lock_UpdateResource (&devp->lock, ioFuns, SRB, schedule_first_io, 0, ae, issue_io, ae, rc);
【０１３１】
図２７ないし３０を参照すると、この例示的実施形態について、更新手順２８０、２９０、３００、および３１０が実行される。これは、たとえばこれら４つのルーチンのアセンブラ・バージョンおよびＣバージョンをアプリケーション・プログラムにコーディングすることによって実行できる。これは非同期であるので、Ｃコード・バージョンまたはＳＲＢコードのいずれかを呼び出せば、これらのルーチンを実行することができる。
【０１３２】
図２７を参照すると、（ae = argである）queue_ioルーチン２８０は、このaeventに即時ビットが設定されているか否か、またはcurrent_issued ２８８がmax_issued ２８７より小さいか否かをテストする、ステップ２８１を含む。このうちどちらかが真であれば、ステップ２８２で、aeventのビジー・ビットはaeventが入出力装置に送信されることを示すように設定され、ステップ２８４でcurrent_issued ２８８が増分され、ステップ２８５でaeが呼出側アプリケーションに戻される。テスト２８１が真でなければ、ステップ２８３でこのaeventが保持待ち行列２７０の末尾に追加され、ステップ２８６でWORK_NOPOSTWORK戻りコードが呼出側アプリケーションに戻される。
【０１３３】
したがって、queue_io ２８０は、queue ２７０またはCurrent_Issuedカウント２８８あるいはその両方を更新するだけである。実際には（多くのパス長さを要する）入出力をスケジューリングせずに、aevent構造のアドレスを後処理ルーチンissue_io ２９０に渡す。入出力を保持待ち行列２７０に追加するだけの場合は、WORK_NOPOSTWORKを戻すことによって、issue_ioルーチン２９０を省略する。
【０１３４】
図２８を参照すると、（ae = prcである）issue_ioルーチン２９０は後処理ルーチンである。これはロックの保持中は実行されないので、装置待ち行列上でのロックの競合が（大幅に）削減される。ステップ２９１は、このaevent（たとえば２７３）で取消しビットが設定されているか否かを判定し、設定されている場合は、ステップ２９２で入出力に、取消しエラーを完全に備えているとのマークを付け、設定されていない場合は、ステップ２９３でオペレーティング・システムが呼び出され、このaevent ２７３によって表された入出力を入出力装置に送信する。
【０１３５】
図２９を参照すると、schedule_io ３００はその両方の引数（aevent構造のアドレスaeと、呼出側が入出力の発行よりも取消しを希望するか否かを示す取消しフラグprc）を使用する資源更新ルーチンである。入出力がすでに装置に送信されている場合は何も実行することはないが、まだ送信されていない場合は保持待ち行列から除去され、取消しを希望しない場合はCurrent_Issued ２８８が増分される。ここでも、発行する入出力がない場合にissue_io ２９０は迂回される。ステップ３０１は、aeが示すaevent（たとえば２７５）にビジー・ビットが設定されているか否かを判定し、設定されている場合は何も実行せずにステップ３０８でWORK_NOPOSTWORKを戻し、設定されていない場合はステップ３０２でビジー・ビットを設定し、ステップ３０３でaevent ２７５を保持待ち行列２７０から除去して、ステップ３０４でcancel_flagが真であるか否かを判定する。cancel_flagが真である場合は、ステップ３０６でaevent構造２７５に取消しビットを設定し、ステップ３０７でaeを呼出側に戻すが、真でない場合は、aeを返す前にcurrent_issued ２８８が増分される。
【０１３６】
図３０を参照すると、schedule_first_io ３１０はステップ３１１を含み、ここで保持待ち行列２７０が空であるか否か、またはcurrent_issued ２８８がmax_issued ２８７よりも大きいか否かを判定する。どちらの条件も真である場合は、ステップ３１３でcurrent_issued ２８８を減分し、ステップ３１６でWORK_NOPOSTWORKを呼出側に戻す。どちらの条件も偽である場合は、ステップ３１２で第１のaeventを保持待ち行列２７０から除去し、ステップ３１４でビジー・ビットをaevent構造に設定して、ステップ３１５で除去したaevent構造のアドレスを呼出側に戻す。
【０１３７】
実施例３．非同期ロックを使用したサービス・スレッドのプールの管理
図３１ないし３７を参照すると、クライアント・スレッドからの作業要求に答えることのできるタスクの有限プールが存在し、作業は（アプリケーションに特有の）何らかの理由でサービス・スレッド上で実行しなければならず、要求は先着順サービスで処理される。この例で、クライアント・スレッドは要求が完了するのを待機しても待機しなくてもよい（すなわち、要求は非同期または同期のいずれでもよい）。アプリケーションまでのクライアント・スレッドまたはサービス・スレッドはいくつでもよい。具体的には、たとえばＩＢＭ  ＤＦＳ／ＭＶＳ製品の場合、ユーザ・タスクはＤＦＳを呼び出してファイル要求を実行する。これらのファイル要求は様々な理由から呼出し側タスクの下では実行できないため、サービス・タスクはユーザ・ファイル要求を選択してこれを実行しなければならない。そこでサービス・スレッドの有限プールが存在し、いくつかのユーザ・タスク（１回にＤＦＳを呼び出すユーザ・プロセスの数とほぼ同数）をサービス・タスク上でディスパッチする必要がある。
【０１３８】
この例では、ロックが定義され、アイドル・サービス・スレッド３２８とクライアント要求３２３〜３２５のための要求待ち行列３２０のリスト３２６が提供されている。要求待ち行列３２０は、Qhead ３２１およびQtail ３２２によってアンカされており、サービス・スレッド３２６はアイドル３２７によってアンカされている。各サービス構造３２８は１つのアイドル・サービス・タスクを表し、そのサービス・タスクに接続されている現在の要求を指す場合もある。
【０１３９】
データ構造３２３はクライアント要求に関連する情報を含み、データ構造３２８はサービス・スレッドを表す。サービス・タスクは、要求待ち行列３２０をチェックし、それが空であることがわかると、そのサービス構造３２８をアイドル・リスト３２６に追加する。クライアント要求が入ってくると、第１にアイドル・リスト３２６に使用可能なサービス・スレッド３２８があるか否かを確認し、ない場合はその要求を要求待ち行列３２０に入れる。待ち行列３２０を更新する場合、タスクの中断または切替えはいっさい必要ない。クライアント・スレッドとサービス・スレッドとの間にはタスク切替えがあり、これは必須である。待ち行列３２０の更新は、待ち行列周囲に堅固な中断ロックを置く従来技術の方法とは異なり、タスクの中断をいっさい伴わない。
【０１４０】
この例では、クライアント・タスクとサーバ・タスクという２つのタイプのタスクがある。この場合、複数タスクの提供は、前述の例のように単に異なるプログラミング言語または実行環境に使用されるだけではなく、適切な機能を確保するために真の非同期更新ルーチンに必要なのである。実際にはコードが同じなので、関数配列が３×２であっても、両タイプのタスク（CLIENTおよびSERVICE）に関する関数はこの例では同一であり、これが図３３ないし図３７に関して下記に説明するプロセスが実装される方法である。
【０１４１】
資源更新ルーチンは下記のとおりである。
【０１４２】
queue_request ３４０は、使用可能なものがあればサービス・スレッド３２８上に要求をディスパッチするために、あるいはその要求を要求待ち行列３２０に追加するために、クライアント・タスクによって呼び出される。
【０１４３】
post_service_thread ３４８は、queue_request ３４０がアイドル・サービス・スレッドを見つけると、スリープ状態のサービス・スレッド３２８を覚醒する。これは、ロックの競合を最小限にするために、ロックの下では実行されない後処理ルーチンである。
【０１４４】
get_next_request ３５０は、（要求は待ち行列の末尾に追加されると想定して）ＦＩＦＯ要求待ち行列３２０の中で最も古い（第１の）要求３２３を除去する。この要求３２３は、（サービス・スレッドが、要求待ち行列３２０上に実行すべき作業がまだあるのを見つけた場合には）サービス・スレッドが要求の処理を完了した後で、スリープ状態に戻る前に実行される。要求３２３は、不必要なWAIT呼出しを避けるために、呼出しサービス・スレッド上で同期的に実行されているかどうかをチェックする。
【０１４５】
この例では、３つの更新ルーチンと２つのタスク・タイプがあるので、更新を処理する関数は３×２配列３２９になる。
【０１４６】
図３３を参照すると、クライアント・スレッドの実行流れは、この要求のための記憶域を取得するステップ３３０と、下記手順を実行するステップ３３１を含む。
lock_UpdateResource (&lock, qFuns, CLIENT,
queue_request, 0, request post_service_thread, 0, rc);
【０１４７】
このクライアント・スレッドが待機を希望すると、ステップ３３２でrequest->ecbを待機し、これを受け取ると、この要求のためにステップ３３０で取得した記憶域を解放する。
【０１４８】
図３４を参照すると、ステップ３３５のコードによってサービス・スレッドの流れが例示されている。サービス・スレッド３２８は、プログラムが終了するまで永続的に実行し、このスレッドのサービス・ブロックのアドレスを含む呼出しに基づいて実行される。ステップ３３５は下記を含む。
0004042945.tif 000008
【０１４９】
ステップ３３５のコードでは、lock_UpdateResource戻りコード（rc）の重要性が示されている。get_next_requestが呼出しスレッド（サービス・タスク）上で実行された場合は要求があるかどうかをチェックし、なければスリープ（WAIT）状態へ進み、あればその要求を実行する。これは必須ではないが、不必要な待機が削減される。
【０１５０】
図３５を参照すると、（request = argである）更新ルーチンqueue_request ３４０はステップ３４１を含み、ここでアイドル・リスト３２８が空であるか否かを判定し、空の場合は、ステップ３４３でこの要求３２５が要求待ち行列３２０の末尾に追加され、ステップ３４６でWORK_NOPOSTWORKが呼出側に戻される。アイドル・リスト３２８が空でない場合は、ステップ３４２でサービス構造３２８がアイドル・リスト３２６から除去され、ステップ３４４でこの要求のアドレスがサービス構造に保存されて、ステップ３４５で除去されたサービス構造のアドレスが呼出側に戻される。すなわち、このルーチン３４０は、アイドル・サービス・スレッド３２８がない場合は要求を要求待ち行列３２０に追加し、非同期更新機能に後処理ルーチンを実行しないように伝えるWORK_NOPOSTWORKを戻す。アイドル・サービス・スレッド３２８が見つかった場合は、これが除去され、非同期更新機能によって後処理ルーチンpost_service_thread ３４８が呼び出される。
【０１５１】
図３６を参照すると、（service = prcである）更新ルーチンpost_service_thread３４８は、ステップ３４９でサービス構造内のecbをポストして、サービス・スレッド３２８を覚醒する。
【０１５２】
図３７を参照すると、更新ルーチンget_next_request（service = arg）３５０は第一に、ステップ３５１で要求待ち行列３２０が空であるか否かを判定する。待ち行列３２０が空の場合は、このサービス構造がアイドル・リスト３２６に追加され、WORK_NOPOSTWORKが呼出側に戻される。待ち行列３２０が空でない場合は、ステップ３５２で次の要求が待ち行列３２０から除去され、ステップ３５４で除去された要求アドレスがサービス構造に保存される。ステップ３５５はsync. flag = WORK_SYNCおよびtask_type = SERVICEであるか否かを判定し、そうであれば、ステップ３５７でWORK_NOPOSTWORKが呼出側に戻され、そうでなければ、ステップ３５６でサービス構造のアドレスが戻される。非同期更新機能によって自動的に更新ルーチンに渡される、sync_flagパラメータとtask_typeパラメータの両方が使用される。get_next_request ３５０コードは、これが（クライアント・タスクではなく）サービス・スレッド上で実行中であるか否かをチェックし、サービス・スレッド上であって同期的に実行される場合には、後処理ルーチンpost_service_thread ３４８は第１の要求を待ち行列３２０から取り出しただけなので、この呼出しを迂回する。この要求アドレスはサービス構造に保存される。サービス・スレッドはlock_UpdateResource戻りコードをチェックし、この場合は作業が同期的に実行されたことを確認し、不必要なWAIT呼出し（これはやや不経済である）を回避する。
【０１５３】
以上のことをまとめると、非同期更新機能を使用すると、（従来技術では）リストに関する競合があった場合は必ず、形式的な中断を使用してこれらのリストを保護する際に発生したアイドル・リストまたは要求待ち行列の更新を待機する必要がなくなる。これらの待ち行列はすべての要求について更新されるので、競合はかなり頻繁に発生する可能性があった。
【０１５４】
実施例４．共用プールへのオブジェクトの戻し
この最後の例では、非同期資源更新機能と標準の同期ロックを組み合わせて、ロックの競合とロックに関するタスク待機を削減する方法について示す。
【０１５５】
一般に、何らかのタイプの資源の何らかのプールがある場合には一種の問題があり、そのプールからのオブジェクトを要求するタスクは、それを取得するまで処理を続行することができない。この場合には、同期的処理を必要とする形式的な中断タイプのロックを使用しなければならない。ただし、オブジェクトでこうしたタスクが実行される場合、それをプールに戻すのに同期的処理は必要なく、本発明の非同期資源更新機能を使用することができる。このような状況では、ロックの競合およびタスク待機を削減するために、非同期資源更新は同期資源更新を行う標準的なロック機構と組み合わせられる。
【０１５６】
ＤＦＳ／ＭＶＳ環境では、クライアントはファイル状況およびデータをＤＦＳファイル・サーバからキャッシュすることができる。これは、キャッシュ・データへの権利を表すトークンを取得することによって実行される。ＤＦＳ／ＭＶＳファイル・サーバには、トークンをキャッシュするためのコードがあり、各ファイルは複数のトークンを有することが可能であって、各クライアントがトークンを有するファイルを複数持つことができる。具体的に言えば、ＤＦＳ／ＭＶＳにはＳＭＢクライアント用のトークン・キャッシュがあり、これがトークンを表すファイルと構造とを表す構造を有する。ファイル構造は大きさが制限されたプール内に保たれ、すべてのファイル構造が現在ファイルに割り当てられている場合は、最後に使用されたスキームを使用してファイル構造を別のファイルに再度割り当てるために、ＬＲＵ再使用スキームを使用する。
【０１５７】
図３８ないし図４０を参照すると、ＳＭＢトークン・キャッシュ３６０は、ファイル識別子に基づいてファイル構造（stkc_file）３６２を即時に見つけるために使用されるハッシュ・テーブル３６１を有する。さらに、どんなファイルにも割り当てられていないファイル構造３７２のフリー・リスト３７０、ならびに現在は割り当てられているが必要であれば別のファイル識別子に再割当て可能なファイル構造３６６〜３６８のＬＲＵ構造待ち行列３６３も有する。待ち行列３６３は、LRUqhead ３６４およびLRUqtail ３６５によってアンカされている。
【０１５８】
stkc_file構造３６６、３７２はファイルを表し、ＤＦＳ内のファイルはその識別子（一続きの数字）によって認識される。ＳＭＢトークン・キャッシュはファイルのマッピングおよびキャッシュを維持し、stkc_file構造３６６、３７２はそれぞれそのファイルのために保持されているトークンのリストと、現在ファイルを参照しているタスクの数を表すrefcountフィールドとを有する。
【０１５９】
ハッシュ・テーブル３６１は、ＤＦＳファイル識別子に基づいたstkc_fileの即時検索に使用される。ハッシュ・テーブルの各行には、ハッシュ・テーブルの行へのアクセスを保護するためのロックがあり、refcountフィールド、ＬＲＵ待ち行列３６３、およびフリー・リスト待ち行列３７０を更新するための大域fileLockがある。
【０１６０】
所与のファイル識別子に関するstkc_file構造３６６、３７２を見つける（取得する）ためのコードは同期ロック技法を使用するので、ここでは説明しない。stkc_file構造で実行されるタスクを示すための非同期コードについて説明する。
【０１６１】
stkc_file refcountは、stkc_fileを参照するタスクごとに増分され、各タスクがファイルの参照を実行するごとに減分される。refcountを減分しそれに基づいてアクションを行うstkc_file_putルーチンは、下記のとおりである。
【０１６２】
0004042945.tif 000009
【０１６３】
キャッシュがファイルのトークンを持っていない場合、そのファイル識別子に関するstkc_fileをキャッシュする理由はない。トークンを持っている場合、そのファイルを別のファイル識別子に再度割り当てることができるので、ファイルは単にＬＲＵ待ち行列に入れておくだけである。refcountが０でない場合は、他にstkc_fileを使用するタスクはないので、何のアクションも実行されない。この処理でハッシュ・テーブル３６１が更新されることがあるので、stkc_fileを含むリストのハッシュ行ロックはロックしておかなければならず、フリー・リスト３７０またはＬＲＵ待ち行列３６３が更新されることがあるので、fileLockは保持しておかなければならない。したがって２つのロックが必要であり、この例では、本発明の非同期更新機能を使用して資源の更新に必要な２つのロックを取得し、その上でタスクが中断する可能性をなくす方法が示されている。
【０１６４】
タスク・タイプは１つ（すべてＣタスク）だけであるが、関数配列は２つある。hashFunsには更新ルーチンが１つしか含まれていない。
【０１６５】
hash_put ３８０は、タスクがstkc_fileで実行されたことを示す主ルーチンである。これは外部ルーチンであり、実行中はハッシュ・テーブル・ロックのみを有する。
【０１６６】
file_put ３８５は、タスクがstkc_fileで実行されたことを示す内部ルーチンである。これがハッシュ・テーブルと主fileLockの両方を実行する場合、ロックは保持される。
【０１６７】
file_postwork ３９５はハッシュ行のロックを解除するのに使用されるルーチンである。
【０１６８】
特別な戻りコードWORK_DONTUNLOCKは、file_putルーチン３８５が別のスレッド上で非同期に実行される場合に、ロックが解除されないことを保証するためにhash_putによって使用される。file_postwork ３９５は、デッドロックを避けるためにハッシュ行ロックを確実に解除する際に使用される。したがって、タスクが中断することなく、ネストされた非同期ロックが実行される。
【０１６９】
図４１を参照すると、stkc_file_putは、stkc_fileのアドレスが戻されることを示す入力filepとして受信する。ステップ３７６では、stkc_fileのファイル識別子がハッシュ行を取得するためにハッシュされ、スロット番号が保存される。ステップ３７７は下記の関数を実行する。
lock_UpdateResource（&hash_table［slot］. lock,
hashFuns, All_TASKS, hash_put, ０, filep, NO_FUNCTION, ０, rc）；
【０１７０】
これは、ファイルがどのハッシュ・テーブル行に格納されるかを最初に決定した後にhash_putを実行する。
【０１７１】
図４２を参照すると、ステップ３８１でhash_put（filep = arg）３８０は以下を実行する。
lock_UpdateResource（&fileLock, fileFuns,
ALL_TASKS, file_put, ０, filep, file_postwork, ０, rc）；
【０１７２】
またステップ３８２でWORK_NOPOSTWORKを戻す。したがって、hash_putはfile_put用のルーチン（fileLockが保持されている間にfile_putを実行することを意味する）を実行し、file_postworkがこれを実行するのでロックを解除しないように、非同期更新機能にWORK_NOPOSTWORK指示を戻す。これは、file_putが別のタスク上で実行される場合に必要であり、実行された場合は、hash_putがこれを戻したときに、ロックがfile_putを実行する予定の他のタスクのために保持されたままであることを保証しなければならない。
【０１７３】
図４３を参照すると、ステップ３８６で、file_put（filep = arg）ルーチン３８５がファイル識別子をハッシュし、スロット番号を保存して、ステップ３８７でファイルの参照カウントを減分する。ステップ３８８は、ファイル参照カウントが現在ゼロであるか否かを判定し、ゼロでなければステップ３９３でハッシュ・スロット番号を呼出側に戻して終了する。ファイル参照カウントがゼロでない場合、ステップ３８９はトークンがこのファイルのために保持されているか否かを判定し、保持されていればステップ３９１でこのファイルをＬＲＵ待ち行列３６３の末尾に追加する。トークンがこのファイルのために保持されていなければ、ステップ３９０でこのファイルをハッシュ行から除去し、ステップ３９２でこのファイルをフリー・リスト３７０に追加する。ステップ３９３はハッシュ・スロット番号を戻して終了する。
【０１７４】
file_putルーチン３８５は、すべての必要な作業を実行する。ハッシュ・スロット番号も戻すので、file_postwork ３９５はどのハッシュ行ロックを解除するのかがわかる。file_put ３８５が実行されているときは、非同期更新機能によって、ハッシュ行とfileLockがどちらも排他的に保持されることが保証される。file_put ３８５が戻ると、fileLockは解除される。
【０１７５】
図４４を参照すると、file_postwork（slot = prc） ３９５はfileLockが保持されていないときに実行され、ステップ３９６でハッシュ・テーブル行のロックが解除される。
【０１７６】
以上のことをまとめると、この例は、WORK_DONTUNLOCK戻りコードの必要性を示しており、非同期資源更新ルーチンの複雑なネストがどのように実行されるかを示している。
【０１７７】
実施例５．追跡テーブル
追跡テーブルは、非同期ロックを介して更新することができる。追跡テーブルはタスクがその作業を実行する間、タスクによって繰り返し更新される。ロックが重いと追跡テーブル上での競合は大きく、パフォーマンスは低下する。本発明の非同期資源更新機能を使用することによって、プログラマは、追跡テーブル用のlock_Init呼出し上にMax_Queued値を指定することで、スレッドが決して過負荷（実際問題としてきわめてまれに発生する）にならないように、追跡テーブル・ロック上で実行可能な待ち行列を制限するための追跡機能を設計することができる。
【０１７８】
【発明の効果】
本発明の利点は、ロックを管理するための改善されたシステムおよび方法が提供されていることである。
【０１７９】
本発明の他の利点は、パフォーマンスが向上したロックを管理するための改善されたシステムおよび方法が提供されていることである。
【０１８０】
本発明の他の利点は、形式的なタスク中断またはＣＰＵスピンを回避するロックを管理するためのシステムおよび方法が提供されていることである。
【０１８１】
本発明の他の利点は、費用のかかるロック競合オーバヘッドを回避するロックを管理するためのシステムおよび方法が提供されていることである。
【０１８２】
本発明の他の利点は、同期的および非同期的の両方でロックを管理するためのシステムおよび方法が提供されていることである。
【０１８３】
代替の実施形態
以上、例示の目的で本発明の固有の実施形態について記載してきたが、本発明の精神および範囲を逸脱することなく、様々な修正が実行可能であることを理解されよう。具体的には、本発明の方法によりコンピュータの動作を制御するために、機械によって読取り可能な信号を記憶するための、固体または流体の伝達媒体、磁気または光学のワイヤ、テープ、またはディスクなどのような、プログラム記憶域またはメモリ装置を提供すること、または本発明のシステムによりその構成要素を構築すること、あるいはその両方は、本発明の範囲内である。
【０１８４】
さらに、この方法の各ステップは、IBM System 390、AS/400、PCなどのどのような汎用コンピュータ上でも実行可能であり、C++、Java、Pl/1、Fortranなどのどのようなプログラミング言語から生成された１つまたは複数の、あるいは１つまたは複数のうちの部分的なプログラム・モジュールまたはオブジェクトにも従っている。さらにまた、前記各ステップあるいは前記各ステップを実装するファイルまたはオブジェクトなどは、特別な目的のハードウェアまたはその目的用に設計された回路モジュールによって実行することができる。
【０１８５】
まとめとして、本発明の構成に関して以下の事項を開示する。
【０１８６】
（１）非同期ロック機能を含むアプリケーションが、タスクの中断またはタスクの切替えなしにロックを介して資源を更新できるようにする方法であって、
第１のタスクが要求する資源を更新するための要求を、前記資源用のロック上の待ち行列に入れるステップと、
前記ロックを解除する前に前記要求を実行するために前記資源上で前記ロックを保持している第２のタスクを動作させるステップとを含む方法。
（２）第１の更新ルーチンおよび第２の更新ルーチンを含む、前記資源を更新するための２つまたはそれ以上の複数の更新ルーチンを提供するステップと、
前記ロックを解除する前に、前記第２のタスクが前記第１の更新ルーチンを実行するステップと、
前記第２のタスクが前記ロックを解除した後に、前記第２の更新ルーチンを選択的に実行するステップとをさらに含み、
それによってロックの競合を削減する、上記（１）に記載の方法。
（３）前記第２のタスクからの戻りコードを前記非同期ロック機能に渡すステップをさらに含む、上記（２）に記載の方法。
（４）前記戻りコードが、前記第２の更新ルーチンの実行を迂回するためのwork_nopostwork戻りコードである、上記（３）に記載の方法。
（５）前記戻りコードが、非同期ロックを複雑にネストするためのwork_dontunlock戻りコードである、上記（３）に記載の方法。
（６）前記更新ルーチンを実行するために複数のタスク・タイプを指定するステップをさらに含み、
それによって多重プログラム言語環境および多重実行環境を選択的に可能にし、タスクを複数の論理クラスに分割する、上記（２）に記載の方法。
（７）非同期ロック機能を含むアプリケーションが、タスクの中断またはタスクの切替えなしに、同期的または非同期的に選択的にロックを介して資源を更新できるようにする方法であって、
第１のタスクが要求する資源を更新するための要求を、前記資源用のロック上の待ち行列に選択的に入れるステップと、
前記ロックを解除する前に前記要求を実行するために前記資源上で前記ロックを保持している第２のタスクを選択的に動作させるステップとを含む方法。
（８）１つまたは複数のユーザ・パラメータを前記アプリケーションから前記更新ルーチンに渡すステップをさらに含む、上記（２）に記載の方法。
（９）sync_flagパラメータを前記非同期ロック機能から前記要求を実行するタスクに渡し、前記パラメータが、前記タスクが呼出しスレッド上で実行中であるかそれとも他のスレッド上で非同期に実行中であるかを指定するステップをさらに含む、上記（１）に記載の方法。
（１０）task_typeパラメータを前記更新ルーチンを実行するタスクに選択的に渡し、前記task_typeパラメータが、前記タスクがその上で実行中のタスクのタイプを指定するステップをさらに含む、上記（６）に記載の方法。
（１１）lock_Resourceマクロまたはunlock_Resourceマクロを選択的に実行するステップと、
ロックを排他的モードで競合なしに取得または解除するのに応答して、後処理コードをインラインで実行するように呼出側に命令するwork_inline戻りコードを戻すステップとをさらに含む、上記（２）に記載の方法。
（１２）最大限に供給されたアプリケーションに応答して、前記ロック上で待ち行列に入れられた非同期更新に対する要求の数を制限するステップをさらに含む、上記（１）に記載の方法。
（１３）前記第２のタスクによって待ち行列に入れられた順序で順次実行されるように、複数のタスクからの前記ロック上にある複数の更新要求を待ち行列に入れるステップをさらに含む、上記（１）に記載の方法。
（１４）非同期ロック機能を含むアプリケーションが、タスクの中断またはタスクの切換えなしにロックを介して資源を更新できるようにするための方法ステップを実行するための、機械実行可能命令のプログラムを有形に実施する、機械読取り可能なプログラム記憶装置であって、前記方法が
第１のタスクが要求する資源を更新するための要求を、前記資源用のロック上の待ち行列に入れるステップと、
前記ロックを解除する前に前記要求を実行するために前記資源上で前記ロックを保持している第２のタスクを動作させるステップとを含む、プログラム記憶装置。
（１５）非同期ロック機能を含むアプリケーションが、タスクの中断またはタスクの切換えなしにロックを介して資源を更新できるようにするための、その中で実施されたコンピュータ読取り可能プログラム・コード手段を含むコンピュータ使用可能媒体を備える製造品であって、製造品中のコンピュータ読取り可能プログラム手段が、
第１のタスクが要求する資源を更新するための要求を、前記資源用のロック上の待ち行列に入れることをコンピュータに実行させるための、コンピュータ読取り可能プログラム・コード手段と、
前記ロックを解除する前に前記要求を実行するために前記資源上で前記ロックを保持している第２のタスクをコンピュータに動作させるための、コンピュータ読取り可能プログラム・コード手段とを含む、製造品。
（１６）共用資源の非同期更新を可能にするためのインターフェース・システムであって、
資源更新要求を定義するための複数のデータ構造と、
呼出し側タスク以外の、前記共用資源上で排他ロックを現在保持している現在のタスクによる実行を待っている更新要求を記述するデータ構造を待ち行列に入れるための待機待ち行列とを含む、インターフェース・システム。
（１７）前記待機待ち行列から除去されたがまだ処理されていないデータ構造を、待ち行列に入れるための取得待ち行列と、
ロックを解除またはダウングレードするための要求用のデータ構造を、待ち行列に入れるためのロック解除待ち行列と、
処理が終了し空き記憶域へ戻す必要のある要求用のデータ構造を、待ち行列に入れるための戻り待ち行列と、
覚醒する必要がある要求、または前記ロックが保持されていないときに実行されることになっている後処理ルーチンを記述する要求用のデータ構造を、待ち行列に入れるためのポスト待ち行列とをさらに含む、上記（１６）に記載のインターフェース・システム。
（１８）前記ロックが、
前記ロックの状態を定義する状態ビットを格納するためのstateパラメータ・フィールドと、
前記待機待ち行列をアンカするためのwait queueフィールドと、
非同期更新呼出しが待機させられる前に待ち行列に入れることのできる更新要求の最大数を指定するためのmaximum queuedフィールドとを含む、上記（１６）に記載のインターフェース・システム。
（１９）前記ロックのstateパラメータが、
前記ロックが排他的に保持されているか否かを指定する第１の標識（Ｅ）と、
前記待機待ち行列が空であるか否かを指定する第２の標識（Ｗ）と、
前記ロックが優先順位の高い状態に保持されているか否かを指定する第３の標識（Ｌ）と、
前記待ち行列に入れることのできる更新要求の最大数を超えたか否かを指定する第４の標識（Ｐ）と、
前記ロック上の前記更新要求の数を指定する第５の標識（Ｒ）とを含む、上記（１６）に記載のインターフェース・システム。
（２０）前記データ構造が、
待ち行列内の次のデータ構造を指す順方向ポインタを格納するためのnextフィールドと、
待ち行列内の前のデータ構造を指す逆方向ポインタを格納するためのpreviousフィールドと、
前記データ構造が待機させられているタスクを表すか否かを指定するためのwaitフィールドと、
要求されたアクションを指定するためのactionフィールドであって、前記アクションがロック取得、ロック解除、ロックのダウングレード、ロックのアップグレード、および作業ユニットのいずれか１つであるactionフィールドと、
取得または解除するロックのタイプを指定するためのtypeフィールドと、
関数配列内で、資源を更新するためにロックを保持している間に実行する関数にアクセスするための、work functionフィールドと、
前記資源更新ルーチン用の第１の関数引数を格納するためのwork processフィールドと、
前記資源更新ルーチン用の第２の関数引数を格納するためのwork argumentフィールドと、
前記資源更新ルーチンの戻り値を格納するためのwork return codeフィールドと、
関数配列にアクセスするためのfunction pointerフィールドと、
前記関数配列内で、後処理関数を識別するためのpost workフィールドと、
後処理引数を格納するためのpost argumentフィールドとを含む、上記（１６）に記載のインターフェース・システム。
【図面の簡単な説明】
【図１】ロックを示す図である。
【図２】図１のロックのstateフィールドを示す図である。
【図３】本発明の好ましい実施形態により、待機作業を定義するためのWAIT_ELEMENTのデータ構造を示す図である。
【図４】作業タイプおよびタスク・タイプを定義するためのフィールドを含む機能配列のフォーマットと、機能アドレスの２次元配列を指すポインタを示す図である。
【図５】本発明の好ましい実施形態のlock_UpdateResource手順を示す流れ図である。
【図６】必要なロックがすでに他の何らかの状態で保持されており、呼出し側タスクがそれを使用できない場合に対処するための、MVS_updateマクロ手順を示す流れ図である。
【図７】ロックを望ましい状態にするための、またはこれが使用できない場合はＬＩＦＯ待機待ち行列に待機要素を追加するための、lock_or_waitルーチンを示す流れ図である。
【図８】図９ないし１７の構成を示す図である。
【図９】タスクがロック解除を試み、待機待ち行列に待機要素があることまたはロック状態のLOCKEDビットがオンになっていることを見つけたとき呼び出される、MVS_unlockルーチンを示す流れ図である。
【図１０】タスクがロック解除を試み、待機待ち行列に待機要素があることまたはロック状態のLOCKEDビットがオンになっていることを見つけたとき呼び出される、MVS_unlockルーチンを示す流れ図である。
【図１１】タスクがロック解除を試み、待機待ち行列に待機要素があることまたはロック状態のLOCKEDビットがオンになっていることを見つけたとき呼び出される、MVS_unlockルーチンを示す流れ図である。
【図１２】タスクがロック解除を試み、待機待ち行列に待機要素があることまたはロック状態のLOCKEDビットがオンになっていることを見つけたとき呼び出される、MVS_unlockルーチンを示す流れ図である。
【図１３】タスクがロック解除を試み、待機待ち行列に待機要素があることまたはロック状態のLOCKEDビットがオンになっていることを見つけたとき呼び出される、MVS_unlockルーチンを示す流れ図である。
【図１４】タスクがロック解除を試み、待機待ち行列に待機要素があることまたはロック状態のLOCKEDビットがオンになっていることを見つけたとき呼び出される、MVS_unlockルーチンを示す流れ図である。
【図１５】タスクがロック解除を試み、待機待ち行列に待機要素があることまたはロック状態のLOCKEDビットがオンになっていることを見つけたとき呼び出される、MVS_unlockルーチンを示す流れ図である。
【図１６】タスクがロック解除を試み、待機待ち行列に待機要素があることまたはロック状態のLOCKEDビットがオンになっていることを見つけたとき呼び出される、MVS_unlockルーチンを示す流れ図である。
【図１７】タスクがロック解除を試み、待機待ち行列に待機要素があることまたはロック状態のLOCKEDビットがオンになっていることを見つけたとき呼び出される、MVS_unlockルーチンを示す流れ図である。
【図１８】タスク待機要素を待ち行列に入れるための、大域待ち行列を示す図である。
【図１９】非同期更新機能の配列を示す図である。
【図２０】スレッドがロック待機に入る必要があるたびに実行される、do_wait手順を示す流れ図である。
【図２１】待機要素を大域待ち行列に選択的に追加するための、add_to_globalルーチンを示す流れ図である。
【図２２】待機要素を大域待ち行列から選択的に除去するための、remove_from_globalルーチンを示す流れ図である。
【図２３】待機要素を空き記憶域に選択的に戻すための、後処理return_waitルーチンを示す流れ図である。
【図２４】大域待ち行列を静止させるためのquiesce_globalルーチンを示す流れ図である。
【図２５】  aeventの保持待ち行列を示す図である。
【図２６】  function_arrayを示す図である。
【図２７】  queue_ioルーチンを示す流れ図である。
【図２８】後処理issue_ioルーチンを示す流れ図である。
【図２９】資源更新ルーチンschedule_ioを示す流れ図である。
【図３０】  schedule_first_ioルーチンを示す流れ図である。
【図３１】  requestの保持待ち行列を示す図である。
【図３２】アイドル・サービス・スレッドの待ち行列を示す図である。
【図３３】クライアント・スレッド実行の流れを示す図である。
【図３４】サービス・スレッド実行の流れを示す疑似コードである。
【図３５】更新ルーチンqueue_requestを示す流れ図である。
【図３６】更新ルーチンpost_service_threadを示す流れ図である。
【図３７】更新ルーチンget_next_requestを示す流れ図である。
【図３８】  hash_tableを示す図である。
【図３９】ＬＲＵ構造待ち行列を示す図である。
【図４０】空き構造ファイルの待ち行列を示す図である。
【図４１】  stkc_file_putルーチンを示す流れ図である。
【図４２】  hash_putルーチンを示す流れ図である。
【図４３】  file_putルーチンを示す流れ図である。
【図４４】  file_postworkルーチンを示す流れ図である。
【図４５】  taken queue、unlock queue、return queue、new queue、wait queue、およびpost queueを含む、本発明の好ましい実施形態により、その間でWAIT_ELEMENTが選択的に移動される、いくつかの待ち行列とリストの高水準システム図である。
【符号の説明】
４００  taken queue（取得待ち行列）
４０１  unlock queue（ロック解除待ち行列）
４０２  return queue（戻り待ち行列）
４０３  new queue（新規待ち行列）
４０４  wait queue（待機待ち行列）
４０５  post queue（ポスト待ち行列）
【図１】
0004042945.tif 000010
【図２】
0004042945.tif 000011
【図３】
0004042945.tif 000012
【図４】
0004042945.tif 000013
【図５】
0004042945.tif 000014
【図６】
0004042945.tif 000015
【図７】
0004042945.tif 000016
【図８】
0004042945.tif 000017
【図９】
0004042945.tif 000018
【図１０】
0004042945.tif 000019
【図１１】
0004042945.tif 000020
【図１２】
0004042945.tif 000021
【図１３】
0004042945.tif 000022
【図１４】
0004042945.tif 000023
【図１５】
0004042945.tif 000024
【図１６】
0004042945.tif 000025
【図１７】
0004042945.tif 000026
【図１８】
0004042945.tif 000027
【図１９】
0004042945.tif 000028
【図２０】
0004042945.tif 000029
【図２１】
0004042945.tif 000030
【図２２】
0004042945.tif 000031
【図２３】
0004042945.tif 000032
【図２４】
0004042945.tif 000033
【図２５】
0004042945.tif 000034
【図２６】
0004042945.tif 000035
【図２７】
0004042945.tif 000036
【図２８】
0004042945.tif 000037
【図２９】
0004042945.tif 000038
【図３０】
0004042945.tif 000039
【図３１】
0004042945.tif 000040
【図３２】
0004042945.tif 000041
【図３３】
0004042945.tif 000042
【図３４】
0004042945.tif 000043
【図３５】
0004042945.tif 000044
【図３６】
0004042945.tif 000045
【図３７】
0004042945.tif 000046
【図３８】
0004042945.tif 000047
【図３９】
0004042945.tif 000048
【図４０】
0004042945.tif 000049
【図４１】
0004042945.tif 000050
【図４２】
0004042945.tif 000051
【図４３】
0004042945.tif 000052
【図４４】
0004042945.tif 000053
【図４５】
0004042945.tif 000054